CavalierContours icon indicating copy to clipboard operation
CavalierContours copied to clipboard

Remove Bluge After offset

Open Prakash19921206 opened this issue 4 years ago • 1 comments

Hi, Thanks for the nice library, i just started to try few values.

Not sure if this is a bug or my mistake in code. Below is the code i'm trying

int main()
{
    Polyline<double> input;
    input.addVertex(0, 0, 0.0);
    input.addVertex(0, 40, 0.0);
    input.addVertex(10, 40, 0.0);
    input.addVertex(10, 10, 0.0);
    input.addVertex(40, 10, 0.0);
    input.addVertex(40, 0, 0.0);

    input.isClosed() = true;
    
    vector<Polyline<double>> results = parallelOffset(input, -2.0);
    vector<PlineVertex<double>> points =  results[0].vertexes();
    for (int i = 0; i < points.size(); i++)
    {
        PlineVertex<double> point = points.at(i);
        cout << "x: " << point.x() << " y: "  << point.y() << " Bluge: "<<point.bulge()<< endl;
    }
}

Below is the output

x: 2 y: 2 Bluge: 0 x: 2 y: 38 Bluge: 0 x: 8 y: 38 Bluge: 0 x: 8 y: 10 Bluge: 0.414214 //Why this Bluge appeared? x: 10 y: 8 Bluge: 0 x: 38 y: 8 Bluge: 0 x: 38 y: 2 Bluge: 0

Is there a way to make sure we get straight lines after offset? expected output was :

x: 2 y: 2 Bluge: 0 x: 2 y: 38 Bluge: 0 x: 8 y: 38 Bluge: 0 x: 8 y: 8 Bluge: 0 x: 38 y: 8 Bluge: 0 x: 38 y: 2 Bluge: 0

I have added reference image below. Reference Offset values

Thanks & Regards Prakash

Prakash19921206 avatar Dec 24 '20 06:12 Prakash19921206

The algorithm always produces offset curves which are exactly parallel to the input curve (unless the offset is too large and it becomes collapsed). To maintain exactly 2 units away from the input curve the offset curve must have an arc to go around the corner at point (10, 10) in your picture. Arcs will always be generated in the case of a convex (relative to the offset curve) bend point regardless of the angle of the bend to maintain constant offset distance.

Currently there are no options to change this behavior, and I don't currently plan on adding any.

Depending on your use case you may be able to write a simple function to process the output curves and remove the arcs by extending the connecting lines to the point where they intersect.

image

From the above image you just need to set the bulge on vertex 1 to zero and insert a new vertex after it at the intersect point. You can find all the places this needs to happen by checking the bulge of the vertexes.

You can use the segTangentVector function to find the points that describe the lines required to find the intersect, see code here: https://github.com/jbuckmccready/CavalierContours/blob/master/include/cavc/plinesegment.hpp#L134. v1 would be the vertex labeled 1 in the picture, v2 would be the vertex labeled 2 in the picture, and pointOnSeg argument would be v1.pos() for one line and v2.pos() for the other.

You can use the intrLineSeg2LineSeg2 function to find the intersect point, see code here: https://github.com/jbuckmccready/CavalierContours/blob/master/include/cavc/intrlineseg2lineseg2.hpp#L32.

Pseudo code something like this:

for each vertex in the offset output:
  if !vertex.bulgeIsZero() then:
    let line1Pt1= vertex.pos()
    let line1Pt2 = segTangentVector(vertex, nextVertex, vertex.pos()) + vertex.pos()
    let line2Pt1 = segTangentVector(vertex, nextVertex, nextVertex.pos()) + nextVertex.pos()
    let line2Pt2 = nextVertex.pos()
    let intersectPoint = intrLineSeg2LineSeg2(line1Pt1, line1Pt2, line2Pt1, line2Pt2)
    insert new vertex with pos at IntersectPoint and bulge equal 0
    vertex.bulge() = 0

NOTE: segTangentVector just returns a vector pointing in the tangent direction from the origin (0, 0), that's why it must be added to the vertex positions to get the actual points on the lines.

jbuckmccready avatar Dec 24 '20 10:12 jbuckmccready