Browse Source

Merge pull request #1906 from scurest/fix-1894

graphics: fix for anti-parallel line segments
Sasha Szpakowski 2 years ago
parent
commit
4e86d45ffd
1 changed files with 30 additions and 5 deletions
  1. 30 5
      src/modules/graphics/Polyline.cpp

+ 30 - 5
src/modules/graphics/Polyline.cpp

@@ -157,7 +157,7 @@ void NoneJoinPolyline::renderEdge(std::vector<Vector2> &anchors, std::vector<Vec
  *    (q + w/2 * ns) + lambda * (q - p) = (q + w/2 * nt) + mu * (r - q)   (u1)
  *    (q - w/2 * ns) + lambda * (q - p) = (q - w/2 * nt) + mu * (r - q)   (u2)
  *
- * with nt,nt being the normals on the segments s = p-q and t = q-r,
+ * with ns,nt being the normals on the segments s = p-q and t = q-r,
  *
  *    ns = perp(s) / |s|
  *    nt = perp(t) / |t|.
@@ -188,11 +188,26 @@ void MiterJoinPolyline::renderEdge(std::vector<Vector2> &anchors, std::vector<Ve
 	anchors.push_back(pointA);
 
 	float det = Vector2::cross(segment, newSegment);
-	if (fabs(det) / (segmentLength * newSegmentLength) < LINES_PARALLEL_EPS && Vector2::dot(segment, newSegment) > 0)
+	if (fabs(det) / (segmentLength * newSegmentLength) < LINES_PARALLEL_EPS)
 	{
 		// lines parallel, compute as u1 = q + ns * w/2, u2 = q - ns * w/2
 		normals.push_back(segmentNormal);
 		normals.push_back(-segmentNormal);
+
+		if (Vector2::dot(segment, newSegment) < 0)
+		{
+			// line reverses direction; because the normal flips, the
+			// triangle strip would twist here, so insert a zero-size
+			// quad to contain the twist
+			//  ____.___.____
+			// |    |\ /|    |
+			// p    q X q    r
+			// |____|/ \|____|
+			anchors.push_back(pointA);
+			anchors.push_back(pointA);
+			normals.push_back(-segmentNormal);
+			normals.push_back(segmentNormal);
+		}
 	}
 	else
 	{
@@ -233,14 +248,24 @@ void BevelJoinPolyline::renderEdge(std::vector<Vector2> &anchors, std::vector<Ve
 	float newSegmentLength = newSegment.getLength();
 
 	float det = Vector2::cross(segment, newSegment);
-	if (fabs(det) / (segmentLength * newSegmentLength) < LINES_PARALLEL_EPS && Vector2::dot(segment, newSegment) > 0)
+	if (fabs(det) / (segmentLength * newSegmentLength) < LINES_PARALLEL_EPS)
 	{
 		// lines parallel, compute as u1 = q + ns * w/2, u2 = q - ns * w/2
 		Vector2 newSegmentNormal = newSegment.getNormal(halfWidth / newSegmentLength);
 		anchors.push_back(pointA);
 		anchors.push_back(pointA);
-		normals.push_back(newSegmentNormal);
-		normals.push_back(-newSegmentNormal);
+		normals.push_back(segmentNormal);
+		normals.push_back(-segmentNormal);
+
+		if (Vector2::dot(segment, newSegment) < 0)
+		{
+			// line reverses direction; same as for miter
+			anchors.push_back(pointA);
+			anchors.push_back(pointA);
+			normals.push_back(-segmentNormal);
+			normals.push_back(segmentNormal);
+		}
+
 		segment = newSegment;
 		segmentLength = newSegmentLength;
 		segmentNormal = newSegmentNormal;