static Vector2[] LineBezierThicknessIntersect(BezierSegment seg, float thickness, Vector2 lineFrom, Vector2 lineTo, out float distanceToIntersection, out Vector2 intersection) { Vector2 tan = ShapeUtils.EvalTangent(seg, 0.0f); Vector2 nrm = Vector2.Perpendicular(tan); Vector2 lastPoint = seg.P0 + nrm * thickness; distanceToIntersection = 0.0f; intersection = new Vector2(float.PositiveInfinity, float.PositiveInfinity); float stepT = 0.01f; float t = 0; while (t < 1.0f) { t += stepT; var point = ShapeUtils.EvalFull(seg, t, out tan, out nrm) + nrm * thickness; intersection = ShapeUtils.IntersectLines(lineFrom, lineTo, lastPoint, point); if (PointOnLineIsWithinSegment(lastPoint, point, intersection)) { distanceToIntersection += (lastPoint - intersection).magnitude; return(new Vector2[] { lastPoint, point }); } distanceToIntersection += (lastPoint - point).magnitude; lastPoint = point; } return(null); }
static void AddSegment(BezierSegment segment, float toT, float halfThickness, JoiningInfo[] joinInfo, float segmentLengthSoFar, List <Vector2> verts, List <UInt16> inds) { Vector2 tanTo, normTo; Vector2 posTo = ShapeUtils.EvalFull(segment, toT, out tanTo, out normTo); Vector2 posThickness = posTo + normTo * halfThickness; Vector2 negThickness = posTo + normTo * -halfThickness; if (joinInfo != null) { if ((joinInfo[0] != null) && (segmentLengthSoFar < joinInfo[0].InnerCornerDistFromStart)) { if (joinInfo[0].RoundPosThickness) { negThickness = joinInfo[0].InnerCornerVertex; } else { posThickness = joinInfo[0].InnerCornerVertex; } } if ((joinInfo[1] != null) && (segmentLengthSoFar > joinInfo[1].InnerCornerDistToEnd)) { if (joinInfo[1].RoundPosThickness) { negThickness = joinInfo[1].InnerCornerVertex; } else { posThickness = joinInfo[1].InnerCornerVertex; } } } System.Diagnostics.Debug.Assert(verts.Count >= 2); int indexStart = verts.Count - 2; verts.Add(posThickness); verts.Add(negThickness); inds.Add((UInt16)(indexStart + 0)); inds.Add((UInt16)(indexStart + 3)); inds.Add((UInt16)(indexStart + 1)); inds.Add((UInt16)(indexStart + 0)); inds.Add((UInt16)(indexStart + 2)); inds.Add((UInt16)(indexStart + 3)); }
static void GenerateTip(BezierSegment segment, bool atStart, float t, PathEnding ending, float halfThickness, TessellationOptions tessellateOptions, List <Vector2> verts, List <UInt16> inds) { // The tip includes the vertices at the end itself Vector2 tan, nrm; var pos = ShapeUtils.EvalFull(segment, t, out tan, out nrm); int indexStart = verts.Count; switch (ending) { case PathEnding.Chop: if (atStart) { verts.Add(pos + nrm * halfThickness); verts.Add(pos - nrm * halfThickness); } else { // Not much, path segments are always expected to be generated perpendicular to the path // at the segment point location, so we don't have to do anything for the ending } break; case PathEnding.Square: if (atStart) { verts.Add(pos + nrm * halfThickness - tan * halfThickness); verts.Add(pos - nrm * halfThickness - tan * halfThickness); verts.Add(pos + nrm * halfThickness); verts.Add(pos - nrm * halfThickness); inds.Add((UInt16)(indexStart + 0)); inds.Add((UInt16)(indexStart + 3)); inds.Add((UInt16)(indexStart + 1)); inds.Add((UInt16)(indexStart + 0)); inds.Add((UInt16)(indexStart + 2)); inds.Add((UInt16)(indexStart + 3)); } else { // Relying on the last two vertices, and just adding two of our own here verts.Add(pos + nrm * halfThickness + tan * halfThickness); verts.Add(pos - nrm * halfThickness + tan * halfThickness); inds.Add((UInt16)(indexStart + 0 - 2)); inds.Add((UInt16)(indexStart + 3 - 2)); inds.Add((UInt16)(indexStart + 1 - 2)); inds.Add((UInt16)(indexStart + 0 - 2)); inds.Add((UInt16)(indexStart + 2 - 2)); inds.Add((UInt16)(indexStart + 3 - 2)); } break; case PathEnding.Round: float arcSign = atStart ? -1 : 1; int arcSegments = CalculateArcSteps(halfThickness, 0, Mathf.PI, tessellateOptions); for (int i = 1; i < arcSegments; i++) { float angle = Mathf.PI * (i / (float)arcSegments); verts.Add(pos + Matrix2D.RotateLH(angle) * nrm * halfThickness * arcSign); } if (atStart) { // Note how we maintain the last two vertices being setup for connection by the rest of the path vertices int indexTipStart = verts.Count; verts.Add(pos + nrm * halfThickness); verts.Add(pos - nrm * halfThickness); for (int i = 1; i < arcSegments; i++) { inds.Add((UInt16)(indexTipStart + 1)); inds.Add((UInt16)(indexStart + i - 1)); inds.Add((UInt16)(indexStart + i)); } } else { inds.Add((UInt16)(indexStart - 1)); inds.Add((UInt16)(indexStart - 2)); inds.Add((UInt16)(indexStart + 0)); for (int i = 1; i < arcSegments - 1; i++) { inds.Add((UInt16)(indexStart - 1)); inds.Add((UInt16)(indexStart + i - 1)); inds.Add((UInt16)(indexStart + i)); } } break; default: System.Diagnostics.Debug.Assert(false); // Joining has its own function break; } }