private Vector3 FindBestSegmentMatch(Vector3 position, Vector2 nVector, SegmentedLine3D previousMatchedSegment, out SegmentedLine3D matchedSegment) { const float angleThreshold = 30f; var pos2D = new Vector2(position.x, position.z); var nVec0 = pos2D - nVector; var nVec1 = pos2D + nVector; var nVec = nVec1 - nVec0; var bestSqrMag = float.MaxValue; var bestPos = Vector3.zero; var matchFound = false; SegmentedLine3D currentMatchedSegment = null; void CheckSegment(SegmentedLine3D segment) { // foreach (var line in segment.lines) for (var i = 0; i < segment.lines.Count; ++i) { var lnStart = segment.lines[i].Start; var lnEnd = segment.lines[i].End; if (i == 0) { lnStart -= segment.lines[i].Vector.normalized; } if (i == segment.lines.Count - 1) { lnEnd += segment.lines[i].Vector.normalized; } var lnStart2D = new Vector2(lnStart.x, lnStart.z); var lnEnd2D = new Vector2(lnEnd.x, lnEnd.z); if (Angle(lnEnd2D - lnStart2D, nVec) < 90 - angleThreshold) { continue; } LineUtils.LineLineIntersection(nVec0, nVec1, lnStart2D, lnEnd2D, out var _, out var segmentsIntersect, out var intersection); if (!segmentsIntersect) { continue; } var sqrMag = (intersection - pos2D).sqrMagnitude; if (sqrMag < bestSqrMag) { matchFound = true; bestSqrMag = sqrMag; currentMatchedSegment = segment; bestPos = Vector3.Lerp(lnStart, lnEnd, (intersection.x - lnStart.x) / (lnEnd.x - lnStart.x)); } } } if (previousMatchedSegment != null) { CheckSegment(previousMatchedSegment); } if (!matchFound) { foreach (var segment in connectedSegments) { CheckSegment(segment); } } matchedSegment = currentMatchedSegment; return(!matchFound ? position : bestPos); }
private static TriangleSearchResult TryGetNextTriangle(Vector2 uvStart, Vector2 uvDir, int triangleStart, int[] tris, Vector2[] uv, List <int> triangleEndMatches, List <Vector2> uvEndMatches, int pointCount, out Vector2 intersection, out int nextTriangleStart) { var inTriangleMatch = -1; for (var i = 0; i < triangleEndMatches.Count; ++i) { if (triangleStart == triangleEndMatches[i]) { inTriangleMatch = i; break; } } if (inTriangleMatch != -1 && (triangleEndMatches[inTriangleMatch] == triangleStart || TryMatchInTriangleEnd(uvStart, uvDir, uvEndMatches[inTriangleMatch], pointCount))) { intersection = uvEndMatches[inTriangleMatch]; nextTriangleStart = triangleStart; return(TriangleSearchResult.WithinTriangle); } nextTriangleStart = -1; intersection = uvStart; var uv1 = uv[tris[triangleStart]]; var uv2 = uv[tris[triangleStart + 1]]; var uv3 = uv[tris[triangleStart + 2]]; var uvEnd = uvStart + uvDir * 50f; uvStart = uvStart - uvDir * 50f; LineUtils.LineLineIntersection(uv1, uv2, uvStart, uvEnd, out _, out var ints12, out var pos12, out _, out _); LineUtils.LineLineIntersection(uv2, uv3, uvStart, uvEnd, out _, out var ints23, out var pos23, out _, out _); LineUtils.LineLineIntersection(uv3, uv1, uvStart, uvEnd, out _, out var ints31, out var pos31, out _, out _); var indexA = -1; var indexB = -1; var bestSqrMag = -1f; if (ints12 && Vector3.SqrMagnitude(pos12 - uvStart) > bestSqrMag) { indexA = tris[triangleStart]; indexB = tris[triangleStart + 1]; bestSqrMag = Vector3.SqrMagnitude(pos12 - uvStart); intersection = pos12; } if (ints23 && Vector3.SqrMagnitude(pos23 - uvStart) > bestSqrMag) { indexA = tris[triangleStart + 1]; indexB = tris[triangleStart + 2]; bestSqrMag = Vector3.SqrMagnitude(pos23 - uvStart); intersection = pos23; } if (ints31 && Vector3.SqrMagnitude(pos31 - uvStart) > bestSqrMag) { indexA = tris[triangleStart + 2]; indexB = tris[triangleStart]; intersection = pos31; } bool TriangleMatches(int a1, int a2, int t1, int t2, int t3) { var a1Match = a1 == t1 || a1 == t2 || a1 == t3; var a2Match = a2 == t1 || a2 == t2 || a2 == t3; return(a1Match && a2Match); } for (var i = 0; i < tris.Length; i += 3) { if (i == triangleStart) { continue; } var t1 = tris[i]; var t2 = tris[i + 1]; var t3 = tris[i + 2]; if (TriangleMatches(indexA, indexB, t1, t2, t3)) { nextTriangleStart = i; break; } } return(nextTriangleStart == -1 ? TriangleSearchResult.EdgeTermination : TriangleSearchResult.Continues); }