public void ShouldCheckNotIntersectWithOtherLine() { var line2D = new Line2d(new Point(2, 3), new Point(4, 5)); var other = new Line2d(new Point(2, 4), new Point(4, 6)); Assert.IsFalse(line2D.HasIntersectWith(other)); }
public void Split_GivenNonIntersectingLine2_ShouldReturnNull() { // Arrange. var v1 = new Point2d(20, 20); var v2 = new Point2d(20, -20); var testObject = new Line2d(v1, v2); v1 = new Point2d(-10, 0); v2 = new Point2d(10, 0); var nonIntersectingLine = new Line2d(v1, v2); // Act. Line2d[] result = testObject.Split(nonIntersectingLine); // Assert. Assert.Null(result); }
private bool CollisionSegments(Line2d line1, Line2d line2, out Vector2 point) // The point of intersection of two segments { point = Vector2.Zero; float ua, ub; if (!GetUaUb(line1, line2, out ua, out ub)) { return(false); } if ((0.0f < ua) && (ua < 1.0f) && (0.0f < ub) && (ub < 1.0f)) { point.X = line1.Point0.X + (line1.Point1.X - line1.Point0.X) * ub; point.Y = line1.Point0.Y + (line1.Point1.Y - line1.Point0.Y) * ub; return(true); } return(false); }
public void ClassifyPointToLine_GivenPointBehind_ShouldReturnBehind( double v1x, double v1y, double v2x, double v2y, double px, double py) { // Arrange. var vertex1 = new Point2d(v1x, v1y); var vertex2 = new Point2d(v2x, v2y); var line = new Line2d(vertex1, vertex2); var point = new Point2d(px, py); // Act. PointClassifier.Classification result = PointClassifier.ClassifyPointToLine(point, line); // Assert. Assert.AreEqual(PointClassifier.Classification.Behind, result); }
public static Dictionary <string, object> SplitByLine(Polygon2d polyOutline, Line2d inputLine, double distance = 5) { if (!ValidateObject.CheckPoly(polyOutline)) { return(null); } List <Point2d> polyOrig = polyOutline.Points; List <Point2d> poly = PolygonUtility.SmoothPolygon(polyOrig, BuildLayout.SPACING); Line2d splitLine = new Line2d(inputLine); Point2d centerPoly = PointUtility.CentroidInPointLists(poly); bool checkSide = ValidateObject.CheckPointSide(splitLine, centerPoly); int orient = ValidateObject.CheckLineOrient(splitLine); if (orient == 0) { if (!checkSide) { splitLine = LineUtility.Move(splitLine, 0, -1 * distance); } else { splitLine = LineUtility.Move(splitLine, 0, 1 * distance); } } else { if (checkSide) { splitLine = LineUtility.Move(splitLine, -1 * distance, 0); } else { splitLine = LineUtility.Move(splitLine, 1 * distance, 0); } } Dictionary <string, object> intersectionReturn = MakeIntersections(poly, splitLine, BuildLayout.SPACING); List <Polygon2d> splittedPoly = (List <Polygon2d>)intersectionReturn["PolyAfterSplit"]; return(new Dictionary <string, object> { { "PolyAfterSplit", (splittedPoly) }, { "SplitLine", (splitLine) } }); }
public void DrawRectangleOutline(Vector2 topLeft, Vector2 bottomRight, PackedLinearColorA color) { topLeft.X += 0.5f; topLeft.Y += 0.5f; bottomRight.X -= 0.5f; bottomRight.Y -= 0.5f; var topRight = new Vector2(bottomRight.X, topLeft.Y); var bottomLeft = new Vector2(topLeft.X, bottomRight.Y); Span <Line2d> lines = stackalloc Line2d[4]; lines[0] = new Line2d(topLeft, topRight, color); lines[1] = new Line2d(topRight, bottomRight, color); lines[2] = new Line2d(bottomRight, bottomLeft, color); lines[3] = new Line2d(bottomLeft, topLeft, color); DrawLines(lines); }
// Removes the lines which are on the poly lines internal static List <Line2d> RemoveDuplicateslinesWithPoly(Polygon2d poly, List <Line2d> lineList) { List <Line2d> cleanLineList = new List <Line2d>(); List <bool> duplicateList = new List <bool>(); for (int i = 0; i < lineList.Count; i++) { Line2d line = new Line2d(lineList[i].StartPoint, lineList[i].EndPoint); cleanLineList.Add(line); duplicateList.Add(false); } for (int i = 0; i < poly.Points.Count; i++) { int b = i + 1; if (i == poly.Points.Count - 1) { b = 0; } Line2d lineA = new Line2d(poly.Points[i], poly.Points[b]); for (int j = 0; j < lineList.Count; j++) { Line2d lineB = lineList[j]; bool checkAdj = GraphicsUtility.LineAdjacencyCheck(lineA, lineB); if (checkAdj) { duplicateList[j] = true; break; } // end of if loop } // end of 2nd for loop } // end of 1st for loop int count = 0; for (int i = 0; i < duplicateList.Count; i++) { if (duplicateList[i] == true) { cleanLineList.RemoveAt(i - count); count += 1; } } return(cleanLineList); }
//offsets an input line by a given distance internal static int DirectionForPointInPoly(Line2d lineInp, Polygon2d poly, double distance) { if (lineInp == null || !ValidateObject.CheckPoly(poly)) { return(0); } Point2d midPt = LineMidPoint(lineInp); Point2d pt1 = OffsetLinePoint(lineInp, midPt, distance); Point2d pt2 = OffsetLinePoint(lineInp, midPt, -1 * distance); if (GraphicsUtility.PointInsidePolygonTest(poly, pt1)) { return(1); } else { return(-1); } }
//################################################################################################################ //this class stores methods realted to GraphicsUtility class which needs to be tested further for reliability //################################################################################################################ // checks if two lines are collinear - not using internal static bool CheckLineCollinear(Line2d lineA, Line2d lineB) { Point2d p1 = lineA.StartPoint; Point2d p2 = lineA.EndPoint; Point2d q1 = lineB.StartPoint; Point2d q2 = lineB.EndPoint; // Find the four orientations needed for general and special cases int o1 = GraphicsUtility.Orientation(p1, q1, p2); int o2 = GraphicsUtility.Orientation(p1, q1, q2); int o3 = GraphicsUtility.Orientation(p2, q2, p1); int o4 = GraphicsUtility.Orientation(p2, q2, q1); // General case if (o1 != o2 && o3 != o4) { return(false); } // p1, q1 and p2 are colinear and p2 lies on segment p1q1 if (o1 == 0 && ValidateObject.CheckOnSegment(p1, p2, q1)) { return(true); } // p1, q1 and p2 are colinear and q2 lies on segment p1q1 if (o2 == 0 && ValidateObject.CheckOnSegment(p1, q2, q1)) { return(true); } // p2, q2 and p1 are colinear and p1 lies on segment p2q2 if (o3 == 0 && ValidateObject.CheckOnSegment(p2, p1, q2)) { return(true); } // p2, q2 and q1 are colinear and q1 lies on segment p2q2 if (o4 == 0 && ValidateObject.CheckOnSegment(p2, q1, q2)) { return(true); } return(false); // Doesn't fall in any of the above cases }
//finds the closest point to a line from a point list public static Point2d ClosestPointToLine(List <Point2d> pt, Line2d line) { double a = line.StartPoint.Y - line.EndPoint.Y; double b = line.EndPoint.X - line.StartPoint.X; double c = line.StartPoint.X * line.EndPoint.Y - line.EndPoint.X * line.StartPoint.Y; int index = 0; double min = Math.Abs(a * pt[0].X + b * pt[0].Y + c); for (int i = 1; i < pt.Count; i++) { double dist = Math.Abs(a * pt[i].X + b * pt[i].Y + c); if (dist < min) { index = i; min = dist; } } return(pt[index]); }
internal static Polygon2d AddpointToPoly(Polygon2d poly, int lineId = 0) { if (!ValidateObject.CheckPoly(poly)) { return(null); } List <Point2d> ptList = new List <Point2d>(); for (int i = 0; i < poly.Points.Count; i++) { if (i == lineId) { Line2d line = poly.Lines[lineId]; } ptList.Add(poly.Points[i]); } return(null); }
public void AngleOfLine() { var line1 = new Line2d(new Point2d(0, 0), new Point2d(100, 0)); var angle = line1.Angle; Assert.AreEqual(90, angle); var line2 = new Line2d(new Point2d(0, 0), new Point2d(100, 100)); angle = line2.Angle; Assert.AreEqual(45, angle); var line3 = new Line2d(new Point2d(0, 0), new Point2d(0, 100)); angle = line3.Angle; Assert.AreEqual(0, angle); var line4 = new Line2d(new Point2d(0, 0), new Point2d(-100, 100)); angle = line4.Angle; Assert.AreEqual(315, angle); var line5 = new Line2d(new Point2d(0, 0), new Point2d(-100, 0)); angle = line5.Angle; Assert.AreEqual(270, angle); var line6 = new Line2d(new Point2d(0, 0), new Point2d(-100, -100)); angle = line6.Angle; Assert.AreEqual(225, angle); var line7 = new Line2d(new Point2d(0, 0), new Point2d(0, -100)); angle = line7.Angle; Assert.AreEqual(180, angle); }
public static void Test() { Line2d line1 = new Line2d(); line1.m_point1 = new Vector2L(0, 0); line1.m_point2 = new Vector2L(100, 100); Line2d line2 = new Line2d(); line2.m_point1 = new Vector2L(0, 100); line2.m_point2 = new Vector2L(100, 0); Vector2L intersectionPoint = new Vector2L(); if (Line2dWithLine2d(line1, line2, ref intersectionPoint)) { Debug.Log("双线相交 交点 " + intersectionPoint); } else { Debug.Log("双线没有相交"); } List <Vector2L> pointList = new List <Vector2L> { new Vector2L(-4.5f, -10f), new Vector2L(-4.5f, 10f), new Vector2L(4.5f, 10f), new Vector2L(4.5f, -10f) }; Convex2d convex1 = new Convex2d(new Vector2L(-5, 0), QuaternionL.Euler(Vector3L.zero), pointList); Convex2d convex2 = new Convex2d(new Vector2L(+5, 0), QuaternionL.Euler(Vector3L.zero), pointList); Debug.Log("凸多边形相交测试1 " + (Convex2dWithConvex2d(convex1, convex2, false, true) != null)); Convex2d convex3 = new Convex2d(new Vector2L(+5, 0), QuaternionL.Euler(new Vector3L(0, -90, 0)), pointList); Debug.Log("凸多边形相交测试2 " + (Convex2dWithConvex2d(convex1, convex3, false, true) != null)); Circle2d circle = new Circle2d(new Vector3L(-5, 0), 5); Debug.Log("圆与凸多边形相交测试1 " + (Circle2dWithConvex2d(circle, convex2, false, true) != null)); Debug.Log("圆与凸多边形相交测试2 " + (Circle2dWithConvex2d(circle, convex3, false, true) != null)); }
private void CreatePoints4() { double a = 4; double b = 7; Line2d plane = new Line2d(a, b); double xSpace = 1.0; int xPointCount = 1; TestPoints.Clear(); for (int i = 0; i < xPointCount; i++) { double x = xSpace * i; double y = plane.GetY(x); TestPoints.Add(new Vector2(x, y)); } }
private void CreatePoints3() { double a = 0.5; double b = 7; Line2d plane = new Line2d(a, b); double xSpace = 1.0; int xPointCount = 200; TestPoints.Clear(); for (int i = 0; i < xPointCount; i++) { double x = xSpace * i + NextRangedRandomNumber(xSpace); double y = plane.GetY(x) + NextRangedRandomNumber(20); TestPoints.Add(new Vector2(x, y)); } }
/// <summary> /// 八边形绘图 /// </summary> /// <param name="AnchorPoint">锚点,八边形下中心点</param> /// <param name="Height">总高</param> /// <param name="Width">总宽</param> /// <param name="F1x">下倒角,x方向</param> /// <param name="F1y">下倒角,y方向</param> /// <param name="F2x">上倒角,x方向</param> /// <param name="F2y">上倒角,y方向</param> public static Polyline Plot8(Database db, Point2d AnchorPoint, double Height, double Width, double F1x = 50, double F1y = 50, double F2x = 200, double F2y = 100) { Polyline PL1 = new Polyline() { Closed = true }; using (Transaction tr = db.TransactionManager.StartTransaction()) { BlockTable blockTbl = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord modelSpace = tr.GetObject(blockTbl[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord; Line2d AxisY = new Line2d(AnchorPoint, AnchorPoint.Convert2D(0, 1)); Point2d p0, p1, p2, p3, p4, p5, p6, p7; p0 = AnchorPoint.Convert2D(-0.5 * Width + F1x, 0); p1 = p0.Mirror(AxisY); p2 = p1.Convert2D(F1x, F1y); p3 = p2.Convert2D(0, Height - F1y - F2y); p4 = p3.Convert2D(-F2x, F2y); p5 = p4.Mirror(AxisY); p6 = p3.Mirror(AxisY); p7 = p2.Mirror(AxisY); PL1.AddVertexAt(0, p0, 0, 0, 0); PL1.AddVertexAt(1, p1, 0, 0, 0); PL1.AddVertexAt(2, p2, 0, 0, 0); PL1.AddVertexAt(3, p3, 0, 0, 0); PL1.AddVertexAt(4, p4, 0, 0, 0); PL1.AddVertexAt(5, p5, 0, 0, 0); PL1.AddVertexAt(6, p6, 0, 0, 0); PL1.AddVertexAt(7, p7, 0, 0, 0); modelSpace.AppendEntity(PL1); tr.AddNewlyCreatedDBObject(PL1, true); tr.Commit(); } return(PL1); }
public void ClassifyLineToLine_GivenCoincidentLines_ShouldReturnCoincident( double line1v1x, double line1v1y, double line1v2x, double line1v2y, double line2v1x, double line2v1y, double line2v2x, double line2v2y) { // Arrange. var line1vertex1 = new Point2d(line1v1x, line1v1y); var line1vertex2 = new Point2d(line1v2x, line1v2y); var line2vertex1 = new Point2d(line2v1x, line2v1y); var line2vertex2 = new Point2d(line2v2x, line2v2y); var line1 = new Line2d(line1vertex1, line1vertex2); var line2 = new Line2d(line2vertex1, line2vertex2); // Act. LineClassifier.Classification result = LineClassifier.ClassifyLineToLine(line1, line2); // Assert. Assert.AreEqual(LineClassifier.Classification.Coincident, result); }
public void ClassifyLineToLine_GivenLine1SpanningLine2_ShouldReturnIntersecting( double line1v1x, double line1v1y, double line1v2x, double line1v2y, double line2v1x, double line2v1y, double line2v2x, double line2v2y) { // Arrange. var line1vertex1 = new Point2d(line1v1x, line1v1y); var line1vertex2 = new Point2d(line1v2x, line1v2y); var line2vertex1 = new Point2d(line2v1x, line2v1y); var line2vertex2 = new Point2d(line2v2x, line2v2y); var line1 = new Line2d(line1vertex1, line1vertex2); var line2 = new Line2d(line2vertex1, line2vertex2); // Act. LineClassifier.Classification result = LineClassifier.ClassifyLineToLine(line1, line2); // Assert. Assert.AreEqual(LineClassifier.Classification.Intersecting, result); }
static double?LinearInterpolation(double[] x, double[] y, double xval) { double?zval = null; Line2d interpolant; int lx = x.Length; int ly = y.Length; if (lx < 2 || ly < 2) { return(zval); } if (lx != ly) { return(zval); } for (int i = 0; i < lx - 1; i++) { if (xval >= x[i] && xval < x[i + 1]) { interpolant = new Line2d(new Point2d(x[i], y[i]), new Point2d(x[i + 1], y[i + 1])); return(interpolant.Interpolation(xval)); } if (xval < x[0]) { interpolant = new Line2d(new Point2d(x[0], y[0]), new Point2d(x[1], y[1])); return(interpolant.Interpolation(xval)); } if (xval >= x[lx - 1]) { interpolant = new Line2d(new Point2d(x[lx - 2], y[lx - 2]), new Point2d(x[lx - 1], y[lx - 1])); return(interpolant.Interpolation(xval)); } } return(zval); }
private void CreatePoints1() { double a = 1; double b = 2; Line2d plane = new Line2d(a, b); double xSpace = 1.0; int xPointCount = 10; List <Vector2> points = new List <Vector2>(); for (int i = 0; i < xPointCount; i++) { double x = xSpace * i; double y = plane.GetY(x); points.Add(new Vector2(x, y)); } TestPoints = points; }
private void CreatePoints2() { double a = 1; double b = 2; Line2d plane = new Line2d(a, b); double xSpace = 1.0; int xPointCount = 100; List <Vector2> points = new List <Vector2>(); for (int i = 0; i < xPointCount; i++) { double x = xSpace * i + NextRangedRandomNumber(xSpace); double y = plane.GetY(x) + NextRangedRandomNumber(5); points.Add(new Vector2(x, y)); } TestPoints = points; }
//checks a line if horizontal or vertical, 0 for horizontal, 1 for vertical internal static int CheckLineOrient(Line2d line) { if (line == null) { return(-1); } double x = Math.Round((line.StartPoint.X - line.EndPoint.X), 2); double y = Math.Round((line.StartPoint.Y - line.EndPoint.Y), 2); if (x == 0) { return(1); } else if (y == 0) { return(0); } else { return(-1); // was 0 prev } }
//checks if two lines are same public static bool IsLineDuplicate(Line2d A, Line2d B) { bool check = false; double eps = 0.1; double mA = (A.EndPoint.Y - A.StartPoint.Y) / (A.EndPoint.X - A.StartPoint.X); double mB = (B.EndPoint.Y - B.StartPoint.Y) / (B.EndPoint.X - B.StartPoint.X); if ((mB - eps < mA && mA < mB + eps) || (mA - eps < mB && mB < mA + eps)) { double intercA = A.StartPoint.Y - mA * A.StartPoint.X; double intercB = B.StartPoint.Y - mB * B.StartPoint.X; if ((intercA - eps < intercA && intercA < intercA + eps) || (intercB - eps < intercB && intercB < intercB + eps)) { check = true; } else { check = false; } } return(check); }
private Point2d ImaginaryIntersect(Point2d line1_pt1, Point2d line1_pt2, Point2d line2_pt1, Point2d line2_pt2) { Line2d line1 = new Line2d(line1_pt1, line1_pt2); Line2d line2 = new Line2d(line2_pt1, line2_pt2); double line1Ang = line1.Direction.Angle; double line2Ang = line2.Direction.Angle; double line1ConAng = line1Ang + Degrees_Radians_Conversion(180, false); double line2ConAng = line2Ang + Degrees_Radians_Conversion(180, false); Point2d RayLine1_pt1 = PolarPoint(line1_pt1, line1Ang, 10000); Point2d RayLine1_pt2 = PolarPoint(line1_pt1, line1ConAng, 10000); Line2d RayLine1 = new Line2d(RayLine1_pt1, RayLine1_pt2); Point2d RayLine2_pt1 = PolarPoint(line2_pt1, line2Ang, 10000); Point2d RayLine2_pt2 = PolarPoint(line2_pt1, line2ConAng, 10000); Line2d RayLine2 = new Line2d(RayLine2_pt1, RayLine2_pt2); Point2d[] col = RayLine1.IntersectWith(RayLine2); return(col[0]); }
/// <summary> /// 求两个familyinstance的旋转中心 /// </summary> /// <param name="pos1"></param> /// <param name="faceOri1"></param> /// <param name="pos2"></param> /// <param name="faceOri2"></param> /// <returns></returns> public static XYZ GetRotateCenter(XYZ pos1, XYZ faceOri1, XYZ pos2, XYZ faceOri2) { //求垂直平分线1 Line pb1 = GetPerpendicularBisector(pos1, pos2); //求垂直平分线2 XYZ pos3 = pos1 + faceOri1; XYZ pos4 = pos2 + faceOri2; Line pb2 = GetPerpendicularBisector(pos3, pos4); Line2d line1 = pb1.ToLine2d(); Line2d line2 = pb2.ToLine2d(); //求垂直平分线的交点 IntrLine2Line2 inter = new IntrLine2Line2(line1, line2); inter.Compute(); if (inter.Quantity != 0) { Vector2d p = inter.Point; XYZ _p = new XYZ(p.x, p.y, pos1.Z); return(_p); } return(null); }
//extends both ends of a line public static Line2d ExtendLine(Line2d line, double extend = 0) { if (extend == 0) { extend = 10000; } double startPtX = 0, startPtY = 0, endPtX = 0, endPtY = 0; if (ValidateObject.CheckLineOrient(line) == 1) { startPtX = line.StartPoint.X; startPtY = line.StartPoint.Y - extend; endPtX = line.EndPoint.X; endPtY = line.EndPoint.Y + extend; } else { startPtX = line.StartPoint.X - extend; startPtY = line.StartPoint.Y; endPtX = line.EndPoint.X + extend; endPtY = line.EndPoint.Y; } return(new Line2d(new Point2d(startPtX, startPtY), new Point2d(endPtX, endPtY))); }
public void Constructor_GivenLines_ShouldBuildTree() { // Arrange. /* (r2) * | * (E1)---------(E2) * | * (B1)--(B2) | (C1)--(C2) * | * (A1)--(A2) | (D1)--(D2) * (r1) * (F1)---------(F2) */ var lines = new List <Line2d> { new Line2d(new Point2d(-5, -5), new Point2d(-2, -5)), // A new Line2d(new Point2d(-5, -8), new Point2d(-2, -8)), // B new Line2d(new Point2d(0, -8), new Point2d(2, -8)), // C new Line2d(new Point2d(0, -5), new Point2d(2, -5)), // D new Line2d(new Point2d(-3, -9), new Point2d(1, -9)), // E new Line2d(new Point2d(-3, 1), new Point2d(1, 1)) // F }; var ray = new Line2d( new Point2d(-1, -1), new Point2d(-1, -10)); var testObject = new Tree(lines); // Act. Line2d result = testObject.FindFirstIntersectingLine(ray); // Assert. Assert.NotNull(result); }
internal void CalcNL(Mesh blackMesh) { if (blackMesh == null) { return; } Vertex vrtx; TriangleQuadTree meshTree = new TriangleQuadTree(blackMesh); TriangleNet.Topology.Triangle trgl = (TriangleNet.Topology.Triangle)meshTree.Query(X, Y); if (trgl == null) { Dictionary <Vertex, double> valuePairs = new Dictionary <Vertex, double>(); Line2d ln; foreach (Vertex item in blackMesh.Vertices) { ln = new Line2d(new Point2d(X, Y), new Point2d(item.X, item.Y)); valuePairs.Add(item, ln.Length); } IOrderedEnumerable <KeyValuePair <Vertex, double> > selected = from v in valuePairs // определяем каждый объект как orderby v.Value // упорядочиваем по возрастанию select v; // выбираем объект List <KeyValuePair <Vertex, double> > lst = selected.ToList(); foreach (TriangleNet.Topology.Triangle item in blackMesh.Triangles) { if (item.Contains(lst[0].Key) && item.Contains(lst[1].Key)) { trgl = item; break; } } } vrtx = new Vertex(X, Y, Number, 2); Interpolation.InterpolateAttributes(vrtx, trgl, 1); NL = Math.Round(vrtx.Attributes[0], 3); }
private bool GetBaseLine() { var ptRes = Ac.Editor.GetPoint("\r\n" + AppServices.Strings.EnterStartPoint); if (!ptRes.IsOK()) { return(false); } var startPt = ptRes.Value; var epPrtOpts = Ac.Editor.GetPromptPointOptions("\r\n" + AppServices.Strings.EnterEndPoint, startPt, true); ptRes = Ac.Editor.GetPoint(epPrtOpts); if (!ptRes.IsOK()) { return(false); } var endPt = ptRes.Value; this.BaseLine = new Line2d(startPt.Convert2d(), endPt.Convert2d()); return(true); }
public void Slice(DynamicRenderMesh mesh, Camera camera) { slicePointsDictionary.Clear(); verticesDictionary.Clear(); slicePoints.Clear(); vertices.Clear(); texCoords.Clear(); indices.Clear(); triangles.Clear(); ResultMeshes.Clear(); FillVertices(mesh, camera); Vector2 A = new Vector2(99999.0f, 99999.0f), B = new Vector2(-99999.0f, -99999.0f); var tempLine = new Line2d(); var workedIndices = new List <int>(); var tempIndices = new List <int>(); foreach (var line in Lines) { for (var i = 0; i < 2; i++) { if (line.A[i] < A[i]) { A[i] = line.A[i]; } if (line.B[i] > B[i]) { B[i] = line.B[i]; } } } for (var i = 0; i < indices.Count / 3; i++) { var index = i * 3; var point0 = vertices[indices[index]]; var point1 = vertices[indices[index + 1]]; var point2 = vertices[indices[index + 2]]; if (!CheckAABB(ref point0, ref point1, ref point2, ref A, ref B)) { for (var j = 0; j < 3; j++) { tempIndices.Add(indices[index + j]); } continue; } for (var j = 0; j < 3; j++) { workedIndices.Add(indices[index + j]); } } if (workedIndices.Count == 0) { return; } var triangle = new Vector3[3]; var triangleT = new Vector2[3]; var tempCollisions = new List <Vector3>(); var tempTexCoords = new List <Vector2>(); var tempCollisionsEdgeIndices = new List <int>(); var newTriangles = new List <int>(); var info0 = CollisionInfo.Zero; var info1 = CollisionInfo.Zero; for (var i = 0; i < sliceLines.Count; i++) { var line = Lines[i]; var sliceLine = sliceLines[i]; var trianglesCount = workedIndices.Count / 3; for (var j = 0; j < trianglesCount; j++) { var index = j * 3; for (var l = 0; l < 3; l++) { triangle[l] = vertices[workedIndices[index + l]]; triangleT[l] = texCoords[workedIndices[index + l]]; } info0 = CollisionInfo.Zero; info1 = CollisionInfo.Zero; tempCollisions.Clear(); tempTexCoords.Clear(); tempCollisionsEdgeIndices.Clear(); newTriangles.Clear(); //looking for a point / intersection point of the triangle and line for (int k = 0, l = 2; k < 3; l = k, k++) { if (info1.Type != CollisionType.CT_NONE) { break; } var tPoint0 = triangle[l]; var tPoint1 = triangle[k]; var tTexCoord0 = triangleT[l]; var tTexCoord1 = triangleT[k]; tempLine.Point0.X = tPoint0.X; tempLine.Point0.Y = tPoint0.Y; tempLine.Point1.X = tPoint1.X; tempLine.Point1.Y = tPoint1.Y; float ua, ub; if (!GetUaUb(tempLine, line, out ua, out ub)) { //lines coincide? //Verify whether some point belongs line segment tempLine //if find - get result and break. } else { if (ub < 0.0f || ub > 1.0f) { continue; } var collisionPoint = tPoint0 + (tPoint1 - tPoint0) * ub; var collisionTexCoord = tTexCoord0 + (tTexCoord1 - tTexCoord0) * ub; if (tempCollisions.Count == 0 || !PointsCompare.Equals(tempCollisions[0], collisionPoint)) { tempCollisions.Add(collisionPoint); tempTexCoords.Add(collisionTexCoord); tempCollisionsEdgeIndices.Add(l); } if (ua < 0.0f || ua > 1.0f) { continue; } var pointType = CollisionType.CT_VERTEX; Vector3 point; Vector2 texCoord; var pointIndex = -1; var edgeIndex = -1; if (ub > 0.0f) { if (ub < 1.0f) { pointType = CollisionType.CT_EDGE; point = tempCollisions.Last(); texCoord = tempTexCoords.Last(); edgeIndex = l; } else { point = tPoint1; texCoord = tTexCoord1; pointIndex = workedIndices[index + k]; } } else { point = tPoint0; texCoord = tTexCoord0; pointIndex = workedIndices[index + l]; } if (info0.Type == CollisionType.CT_NONE) { info0.PointIndex = pointIndex; info0.Type = pointType; info0.Position = point; info0.TexCoord = texCoord; info0.EdgeIndex = edgeIndex; } else { if (pointIndex == -1 || info0.PointIndex != pointIndex) { info1.PointIndex = pointIndex; info1.Type = pointType; info1.Position = point; info1.TexCoord = texCoord; info1.EdgeIndex = edgeIndex; } } } } if (info1.Type == CollisionType.CT_NONE) { if (tempCollisions.Count == 0) { if (info0.Type == CollisionType.CT_NONE) { continue; } } else { if (tempCollisions.Count > 1) { //Perhaps the point inside the triangle var dir = line.Direction; for (var l = 0; l < 2; l++) { var p = l == 0 ? line.Point0 : line.Point1; if (PointInTriangle(ref triangle[0], ref triangle[1], ref triangle[2], ref p)) { var v0 = tempCollisions[1].Xy - tempCollisions[0].Xy; var v1 = p - tempCollisions[0].Xy; var k = (v1.Length / v0.Length); var z = tempCollisions[0].Z + (tempCollisions[1].Z - tempCollisions[0].Z) * k; var t = tempTexCoords[0] + (tempTexCoords[1] - tempTexCoords[0]) * k; if (info0.Type == CollisionType.CT_NONE) { info0.Type = CollisionType.CT_INSIDE; info0.Position = new Vector3(p.X, p.Y, z); info0.TexCoord = t; if (Vector2.Dot(dir, v0) > 0.0f) { info0.EdgeIndex = tempCollisionsEdgeIndices[0]; } else { info0.EdgeIndex = tempCollisionsEdgeIndices[1]; } tempCollisionsEdgeIndices.Remove(info0.EdgeIndex); } else { info1.Type = CollisionType.CT_INSIDE; info1.Position = new Vector3(p.X, p.Y, z); info1.TexCoord = t; info1.EdgeIndex = tempCollisionsEdgeIndices[0]; } } } } } } if (info0.Type == CollisionType.CT_NONE) { continue; } //Create new triangles, if we have two points of intersection, and they are not vertices int pi1 = 0, pi0 = 0; if (info1.Type != CollisionType.CT_NONE && (info0.Type != CollisionType.CT_VERTEX || info1.Type != CollisionType.CT_VERTEX)) { if (info1.Type == CollisionType.CT_VERTEX || (info1.Type == CollisionType.CT_EDGE && info0.Type == CollisionType.CT_INSIDE) || (info1.Type == CollisionType.CT_EDGE && info0.Type == CollisionType.CT_EDGE && (info0.EdgeIndex + 1) % 3 != info1.EdgeIndex) || (info0.Type == CollisionType.CT_INSIDE && info1.Type == CollisionType.CT_INSIDE && (info0.EdgeIndex + 1) % 3 != info1.EdgeIndex)) { var temp = info1; info1 = info0; info0 = temp; } if (!verticesDictionary.TryGetValue(info1.Position, out pi1)) { pi1 = vertices.Count; vertices.Add(info1.Position); texCoords.Add(info1.TexCoord); verticesDictionary.Add(info1.Position, pi1); } if (info0.Type == CollisionType.CT_VERTEX) //One point of intersection coincides with the vertex { pi0 = info0.PointIndex; int i0 = workedIndices[index], i1 = workedIndices[index + 1], i2 = workedIndices[index + 2]; if (i0 == info0.PointIndex) { i0 = i2; i2 = i1; } else { if (i2 == info0.PointIndex) { i2 = i0; i0 = i1; } } i1 = info0.PointIndex; newTriangles.AddRange(new[] { i0, i1, pi1, i1, i2, pi1 }); if (info1.Type == CollisionType.CT_INSIDE) //The second point inside the triangle { newTriangles.AddRange(new[] { i2, i0, pi1 }); } } else { if (!verticesDictionary.TryGetValue(info0.Position, out pi0)) { pi0 = vertices.Count; vertices.Add(info0.Position); texCoords.Add(info0.TexCoord); verticesDictionary.Add(info0.Position, pi0); } if (info1.Type != info0.Type) //One point crosses the brink, the second inside the triangle { var prev = info0.EdgeIndex == 0 ? 2 : info0.EdgeIndex - 1; prev = workedIndices[index + prev]; var next = info0.EdgeIndex == 2 ? 0 : info0.EdgeIndex + 1; next = workedIndices[index + next]; var curr = workedIndices[index + info0.EdgeIndex]; newTriangles.AddRange(new[] { prev, curr, pi1, curr, pi0, pi1, pi0, next, pi1, next, prev, pi1 }); } else { var c0 = workedIndices[index + info0.EdgeIndex]; var c1 = workedIndices[index + info1.EdgeIndex]; var c2 = workedIndices[index + ((info1.EdgeIndex + 1) % 3)]; if (info0.Type == CollisionType.CT_EDGE) { newTriangles.AddRange(new[] { c0, pi0, pi1, pi0, c1, pi1, pi1, c2, c0 }); } else { newTriangles.AddRange(new[] { c0, c1, pi0, c1, pi1, pi0, c1, c2, pi1, c2, c0, pi1, c0, pi0, pi1 }); } } } } int slicePointIndex; SlicePoint slicePoint; for (var l = 0; l < 2; l++) { if (l == 1 && info1.Type == CollisionType.CT_NONE) { break; } var position = l == 0 ? info0.Position.Xy : info1.Position.Xy; var pointIndex = l == 0 ? pi0 : pi1; if (!slicePointsDictionary.TryGetValue(position, out slicePointIndex)) { slicePoint = new SlicePoint { Coordinate = position }; slicePoint.Lines.Add(sliceLine); slicePoint.PreparePoint(); slicePointIndex = slicePoints.Count; slicePoints.Add(slicePoint); slicePointsDictionary.Add(position, slicePointIndex); } else { slicePoint = slicePoints[slicePointIndex]; } if (!slicePoint.Indices.Contains(pointIndex)) { slicePoint.Indices.Add(pointIndex); } } if (newTriangles.Count > 0) { for (var l = 0; l < 3; l++) { workedIndices[index + l] = newTriangles[l]; } newTriangles.RemoveRange(0, 3); workedIndices.InsertRange(index, newTriangles); var count = (newTriangles.Count / 3); j += count; trianglesCount += count; } } } for (var i = 0; i < workedIndices.Count / 3; i++) { var index = i * 3; var t = new Triangle(); for (var j = 0; j < 3; j++) { t.Indices[j] = workedIndices[index + j]; } triangles.Add(i, new TrianleConnections { Triangle = t }); } var ind = new List <int>(); var tempTriangle = new Triangle(); tempTriangle.Indices[1] = -1; foreach (var point in slicePoints) { point.PreparePoint(); foreach (var index in point.Indices) { ind.Clear(); ind.Add(index); tempTriangle.Indices[0] = index; //Duplicate the verticle several times for (var i = 1; i < point.Directions.Count; i++) { ind.Add(vertices.Count); vertices.Add(vertices[index]); texCoords.Add(texCoords[index]); } foreach (var t in triangles) { var tr = t.Value.Triangle; var id = Triangle.TriangleEquals(ref tempTriangle, ref tr); if (id > -1) { var center = (vertices[tr.Indices[0]].Xy + vertices[tr.Indices[1]].Xy + vertices[tr.Indices[2]].Xy) / 3.0f; var dir = (center - point.Coordinate).Normalized(); var angle = SlicePoint.GetAngle(ref dir); var ii = point.Directions.Count - 1; for (var j = 0; j < point.Directions.Count; j++) { if (angle < point.Directions[j]) { break; } ii = j; } tr.Indices[id] = ind[ii]; } } } } var invTransform = mesh.Transform * camera.ViewMatrix; invTransform.Invert(); for (var i = 0; i < vertices.Count; i++) { vertices[i] = Vector3.Transform(vertices[i], invTransform); } workedIndices.Clear(); foreach (var t in triangles) { foreach (var i in t.Value.Triangle.Indices) { workedIndices.Add(i); } } workedIndices.AddRange(tempIndices); triangleConnections.Clear(); triangles.Clear(); for (var i = 0; i < workedIndices.Count / 3; i++) { var index = i * 3; var t = new Triangle(); for (var j = 0; j < 3; j++) { t.Indices[j] = workedIndices[index + j]; List <int> l; if (!triangleConnections.TryGetValue(t.Indices[j], out l)) { l = new List <int>(); triangleConnections.Add(t.Indices[j], l); } l.Add(i); } triangles.Add(i, new TrianleConnections { Triangle = t }); } var mainMesh = true; while (triangles.Count > 0) { foundedTriangles.Clear(); FillTriangles(triangles.First().Key); if (mainMesh) { mesh.Create(vertices, texCoords, foundedTriangles, mesh.Material.DiffuseTextureMap, mesh.Material.TransparentTextureMap, mesh.TextureAngle, mesh.TextureSize); mainMesh = false; } else { var tmpMesh = new DynamicRenderMesh(MeshType.Hair); tmpMesh.Create(vertices, texCoords, foundedTriangles, mesh.Material.DiffuseTextureMap, mesh.Material.TransparentTextureMap, mesh.TextureAngle, mesh.TextureSize); tmpMesh.Transform = mesh.Transform; tmpMesh.Material.DiffuseColor = mesh.Material.DiffuseColor; tmpMesh.MeshAngle = mesh.MeshAngle; tmpMesh.MeshSize = mesh.MeshSize; var info = tmpMesh.GetMeshInfo(); var center = Vector3.Zero; var scale = PickingController.GetHairScale(ProgramCore.Project.ManType); foreach (var vert in info.Positions) { center.X += vert.X * scale; center.Y += vert.Y * scale; center.Z += vert.Z * scale; } center /= info.Positions.Count; tmpMesh.Position = center; ResultMeshes.Add(tmpMesh); } } }
public static LineSegment2d[] GetTangentsTo( [NotNull] this CircularArc2d arc, [NotNull] CircularArc2d other, TangentType flags) { // check if a circle is inside the other var dist = arc.Center.GetDistanceTo(other.Center); if (dist - Math.Abs(arc.Radius - other.Radius) <= Tolerance.Global.EqualPoint) { return(null); } // check if circles overlap var overlap = arc.Radius + other.Radius >= dist; if (overlap && flags == TangentType.Inner) { return(null); } CircularArc2d tmp1; Point2d[] inters; Vector2d vec1, vec2, vec = other.Center - arc.Center; int i, j; var result = new LineSegment2d[(int)flags == 3 && !overlap ? 4 : 2]; // outer tangents if ((flags & TangentType.Outer) > 0) { if (Math.Abs(arc.Radius - other.Radius) < 0.001) { var perp = new Line2d(arc.Center, vec.GetPerpendicularVector()); inters = arc.IntersectWith(perp); if (inters == null) { return(null); } vec1 = (inters[0] - arc.Center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1; j = i ^ 1; result[i] = new LineSegment2d(inters[0], inters[0] + vec); result[j] = new LineSegment2d(inters[1], inters[1] + vec); } else { var center = arc.Radius < other.Radius ? other.Center : arc.Center; tmp1 = new CircularArc2d(center, Math.Abs(arc.Radius - other.Radius)); var tmp2 = new CircularArc2d(arc.Center + vec / 2.0, dist / 2.0); inters = tmp1.IntersectWith(tmp2); if (inters == null) { return(null); } vec1 = (inters[0] - center).GetNormal(); vec2 = (inters[1] - center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1; j = i ^ 1; result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1 * other.Radius); result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2 * other.Radius); } } // inner tangents if ((flags & TangentType.Inner) > 0 && !overlap) { var ratio = arc.Radius / (arc.Radius + other.Radius) / 2.0; tmp1 = new CircularArc2d(arc.Center + vec * ratio, dist * ratio); inters = arc.IntersectWith(tmp1); if (inters == null) { return(null); } vec1 = (inters[0] - arc.Center).GetNormal(); vec2 = (inters[1] - arc.Center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 2 : 3; j = i == 2 ? 3 : 2; result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1.Negate() * other.Radius); result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2.Negate() * other.Radius); } return(result); }
public void Slice(DynamicRenderMesh mesh, Camera camera) { slicePointsDictionary.Clear(); verticesDictionary.Clear(); slicePoints.Clear(); vertices.Clear(); texCoords.Clear(); indices.Clear(); triangles.Clear(); ResultMeshes.Clear(); FillVertices(mesh, camera); Vector2 A = new Vector2(99999.0f, 99999.0f), B = new Vector2(-99999.0f, -99999.0f); var tempLine = new Line2d(); var workedIndices = new List<int>(); var tempIndices = new List<int>(); foreach (var line in Lines) { for (var i = 0; i < 2; i++) { if (line.A[i] < A[i]) A[i] = line.A[i]; if (line.B[i] > B[i]) B[i] = line.B[i]; } } for (var i = 0; i < indices.Count / 3; i++) { var index = i * 3; var point0 = vertices[indices[index]]; var point1 = vertices[indices[index + 1]]; var point2 = vertices[indices[index + 2]]; if (!CheckAABB(ref point0, ref point1, ref point2, ref A, ref B)) { for (var j = 0; j < 3; j++) tempIndices.Add(indices[index + j]); continue; } for (var j = 0; j < 3; j++) workedIndices.Add(indices[index + j]); } if (workedIndices.Count == 0) return; var triangle = new Vector3[3]; var triangleT = new Vector2[3]; var tempCollisions = new List<Vector3>(); var tempTexCoords = new List<Vector2>(); var tempCollisionsEdgeIndices = new List<int>(); var newTriangles = new List<int>(); var info0 = CollisionInfo.Zero; var info1 = CollisionInfo.Zero; for (var i = 0; i < sliceLines.Count; i++) { var line = Lines[i]; var sliceLine = sliceLines[i]; var trianglesCount = workedIndices.Count / 3; for (var j = 0; j < trianglesCount; j++) { var index = j * 3; for (var l = 0; l < 3; l++) { triangle[l] = vertices[workedIndices[index + l]]; triangleT[l] = texCoords[workedIndices[index + l]]; } info0 = CollisionInfo.Zero; info1 = CollisionInfo.Zero; tempCollisions.Clear(); tempTexCoords.Clear(); tempCollisionsEdgeIndices.Clear(); newTriangles.Clear(); //looking for a point / intersection point of the triangle and line for (int k = 0, l = 2; k < 3; l = k, k++) { if (info1.Type != CollisionType.CT_NONE) break; var tPoint0 = triangle[l]; var tPoint1 = triangle[k]; var tTexCoord0 = triangleT[l]; var tTexCoord1 = triangleT[k]; tempLine.Point0.X = tPoint0.X; tempLine.Point0.Y = tPoint0.Y; tempLine.Point1.X = tPoint1.X; tempLine.Point1.Y = tPoint1.Y; float ua, ub; if (!GetUaUb(tempLine, line, out ua, out ub)) { //lines coincide? //Verify whether some point belongs line segment tempLine //if find - get result and break. } else { if (ub < 0.0f || ub > 1.0f) continue; var collisionPoint = tPoint0 + (tPoint1 - tPoint0) * ub; var collisionTexCoord = tTexCoord0 + (tTexCoord1 - tTexCoord0) * ub; if (tempCollisions.Count == 0 || !PointsCompare.Equals(tempCollisions[0], collisionPoint)) { tempCollisions.Add(collisionPoint); tempTexCoords.Add(collisionTexCoord); tempCollisionsEdgeIndices.Add(l); } if (ua < 0.0f || ua > 1.0f) continue; var pointType = CollisionType.CT_VERTEX; Vector3 point; Vector2 texCoord; var pointIndex = -1; var edgeIndex = -1; if (ub > 0.0f) { if (ub < 1.0f) { pointType = CollisionType.CT_EDGE; point = tempCollisions.Last(); texCoord = tempTexCoords.Last(); edgeIndex = l; } else { point = tPoint1; texCoord = tTexCoord1; pointIndex = workedIndices[index + k]; } } else { point = tPoint0; texCoord = tTexCoord0; pointIndex = workedIndices[index + l]; } if (info0.Type == CollisionType.CT_NONE) { info0.PointIndex = pointIndex; info0.Type = pointType; info0.Position = point; info0.TexCoord = texCoord; info0.EdgeIndex = edgeIndex; } else { if (pointIndex == -1 || info0.PointIndex != pointIndex) { info1.PointIndex = pointIndex; info1.Type = pointType; info1.Position = point; info1.TexCoord = texCoord; info1.EdgeIndex = edgeIndex; } } } } if (info1.Type == CollisionType.CT_NONE) { if (tempCollisions.Count == 0) { if (info0.Type == CollisionType.CT_NONE) continue; } else { if (tempCollisions.Count > 1) { //Perhaps the point inside the triangle var dir = line.Direction; for (var l = 0; l < 2; l++) { var p = l == 0 ? line.Point0 : line.Point1; if (PointInTriangle(ref triangle[0], ref triangle[1], ref triangle[2], ref p)) { var v0 = tempCollisions[1].Xy - tempCollisions[0].Xy; var v1 = p - tempCollisions[0].Xy; var k = (v1.Length / v0.Length); var z = tempCollisions[0].Z + (tempCollisions[1].Z - tempCollisions[0].Z) * k; var t = tempTexCoords[0] + (tempTexCoords[1] - tempTexCoords[0]) * k; if (info0.Type == CollisionType.CT_NONE) { info0.Type = CollisionType.CT_INSIDE; info0.Position = new Vector3(p.X, p.Y, z); info0.TexCoord = t; if (Vector2.Dot(dir, v0) > 0.0f) info0.EdgeIndex = tempCollisionsEdgeIndices[0]; else info0.EdgeIndex = tempCollisionsEdgeIndices[1]; tempCollisionsEdgeIndices.Remove(info0.EdgeIndex); } else { info1.Type = CollisionType.CT_INSIDE; info1.Position = new Vector3(p.X, p.Y, z); info1.TexCoord = t; info1.EdgeIndex = tempCollisionsEdgeIndices[0]; } } } } } } if (info0.Type == CollisionType.CT_NONE) continue; //Create new triangles, if we have two points of intersection, and they are not vertices int pi1 = 0, pi0 = 0; if (info1.Type != CollisionType.CT_NONE && (info0.Type != CollisionType.CT_VERTEX || info1.Type != CollisionType.CT_VERTEX )) { if (info1.Type == CollisionType.CT_VERTEX || (info1.Type == CollisionType.CT_EDGE && info0.Type == CollisionType.CT_INSIDE) || (info1.Type == CollisionType.CT_EDGE && info0.Type == CollisionType.CT_EDGE && (info0.EdgeIndex + 1) % 3 != info1.EdgeIndex) || (info0.Type == CollisionType.CT_INSIDE && info1.Type == CollisionType.CT_INSIDE && (info0.EdgeIndex + 1) % 3 != info1.EdgeIndex)) { var temp = info1; info1 = info0; info0 = temp; } if (!verticesDictionary.TryGetValue(info1.Position, out pi1)) { pi1 = vertices.Count; vertices.Add(info1.Position); texCoords.Add(info1.TexCoord); verticesDictionary.Add(info1.Position, pi1); } if (info0.Type == CollisionType.CT_VERTEX) //One point of intersection coincides with the vertex { pi0 = info0.PointIndex; int i0 = workedIndices[index], i1 = workedIndices[index + 1], i2 = workedIndices[index + 2]; if (i0 == info0.PointIndex) { i0 = i2; i2 = i1; } else { if (i2 == info0.PointIndex) { i2 = i0; i0 = i1; } } i1 = info0.PointIndex; newTriangles.AddRange(new[] { i0, i1, pi1, i1, i2, pi1 }); if (info1.Type == CollisionType.CT_INSIDE) //The second point inside the triangle newTriangles.AddRange(new[] { i2, i0, pi1 }); } else { if (!verticesDictionary.TryGetValue(info0.Position, out pi0)) { pi0 = vertices.Count; vertices.Add(info0.Position); texCoords.Add(info0.TexCoord); verticesDictionary.Add(info0.Position, pi0); } if (info1.Type != info0.Type) //One point crosses the brink, the second inside the triangle { var prev = info0.EdgeIndex == 0 ? 2 : info0.EdgeIndex - 1; prev = workedIndices[index + prev]; var next = info0.EdgeIndex == 2 ? 0 : info0.EdgeIndex + 1; next = workedIndices[index + next]; var curr = workedIndices[index + info0.EdgeIndex]; newTriangles.AddRange(new[] { prev, curr, pi1, curr, pi0, pi1, pi0, next, pi1, next, prev, pi1 }); } else { var c0 = workedIndices[index + info0.EdgeIndex]; var c1 = workedIndices[index + info1.EdgeIndex]; var c2 = workedIndices[index + ((info1.EdgeIndex + 1) % 3)]; if (info0.Type == CollisionType.CT_EDGE) { newTriangles.AddRange(new[] { c0, pi0, pi1, pi0, c1, pi1, pi1, c2, c0 }); } else { newTriangles.AddRange(new[] { c0, c1, pi0, c1, pi1, pi0, c1, c2, pi1, c2, c0, pi1, c0, pi0, pi1}); } } } } int slicePointIndex; SlicePoint slicePoint; for (var l = 0; l < 2; l++) { if (l == 1 && info1.Type == CollisionType.CT_NONE) break; var position = l == 0 ? info0.Position.Xy : info1.Position.Xy; var pointIndex = l == 0 ? pi0 : pi1; if (!slicePointsDictionary.TryGetValue(position, out slicePointIndex)) { slicePoint = new SlicePoint { Coordinate = position }; slicePoint.Lines.Add(sliceLine); slicePoint.PreparePoint(); slicePointIndex = slicePoints.Count; slicePoints.Add(slicePoint); slicePointsDictionary.Add(position, slicePointIndex); } else slicePoint = slicePoints[slicePointIndex]; if (!slicePoint.Indices.Contains(pointIndex)) slicePoint.Indices.Add(pointIndex); } if (newTriangles.Count > 0) { for (var l = 0; l < 3; l++) workedIndices[index + l] = newTriangles[l]; newTriangles.RemoveRange(0, 3); workedIndices.InsertRange(index, newTriangles); var count = (newTriangles.Count / 3); j += count; trianglesCount += count; } } } for (var i = 0; i < workedIndices.Count / 3; i++) { var index = i * 3; var t = new Triangle(); for (var j = 0; j < 3; j++) t.Indices[j] = workedIndices[index + j]; triangles.Add(i, new TrianleConnections { Triangle = t }); } var ind = new List<int>(); var tempTriangle = new Triangle(); tempTriangle.Indices[1] = -1; foreach (var point in slicePoints) { point.PreparePoint(); foreach (var index in point.Indices) { ind.Clear(); ind.Add(index); tempTriangle.Indices[0] = index; //Duplicate the verticle several times for (var i = 1; i < point.Directions.Count; i++) { ind.Add(vertices.Count); vertices.Add(vertices[index]); texCoords.Add(texCoords[index]); } foreach (var t in triangles) { var tr = t.Value.Triangle; var id = Triangle.TriangleEquals(ref tempTriangle, ref tr); if (id > -1) { var center = (vertices[tr.Indices[0]].Xy + vertices[tr.Indices[1]].Xy + vertices[tr.Indices[2]].Xy) / 3.0f; var dir = (center - point.Coordinate).Normalized(); var angle = SlicePoint.GetAngle(ref dir); var ii = point.Directions.Count - 1; for (var j = 0; j < point.Directions.Count; j++) { if (angle < point.Directions[j]) break; ii = j; } tr.Indices[id] = ind[ii]; } } } } var invTransform = mesh.Transform * camera.ViewMatrix; invTransform.Invert(); for (var i = 0; i < vertices.Count; i++) { vertices[i] = Vector3.Transform(vertices[i], invTransform); } workedIndices.Clear(); foreach (var t in triangles) { foreach (var i in t.Value.Triangle.Indices) workedIndices.Add(i); } workedIndices.AddRange(tempIndices); triangleConnections.Clear(); triangles.Clear(); for (var i = 0; i < workedIndices.Count / 3; i++) { var index = i * 3; var t = new Triangle(); for (var j = 0; j < 3; j++) { t.Indices[j] = workedIndices[index + j]; List<int> l; if (!triangleConnections.TryGetValue(t.Indices[j], out l)) { l = new List<int>(); triangleConnections.Add(t.Indices[j], l); } l.Add(i); } triangles.Add(i, new TrianleConnections { Triangle = t }); } var mainMesh = true; while (triangles.Count > 0) { foundedTriangles.Clear(); FillTriangles(triangles.First().Key); if (mainMesh) { mesh.Create(vertices, texCoords, foundedTriangles, mesh.Material.DiffuseTextureMap, mesh.Material.TransparentTextureMap, mesh.TextureAngle, mesh.TextureSize); mainMesh = false; } else { var tmpMesh = new DynamicRenderMesh(MeshType.Hair); tmpMesh.Create(vertices, texCoords, foundedTriangles, mesh.Material.DiffuseTextureMap, mesh.Material.TransparentTextureMap, mesh.TextureAngle, mesh.TextureSize); tmpMesh.Transform = mesh.Transform; tmpMesh.Material.DiffuseColor = mesh.Material.DiffuseColor; tmpMesh.MeshAngle = mesh.MeshAngle; tmpMesh.MeshSize = mesh.MeshSize; var info = tmpMesh.GetMeshInfo(1.0f); var center = Vector3.Zero; var scale = PickingController.GetHairScale(ProgramCore.Project.ManType); foreach (var vert in info.Positions) { center.X += vert.X * scale; center.Y += vert.Y * scale; center.Z += vert.Z * scale; } center /= info.Positions.Count; tmpMesh.Position = center; ResultMeshes.Add(tmpMesh); } } }
/// <summary> /// Returns the tangents between the active CircularArc2d instance complete circle and another one. /// </summary> /// <remarks> /// Tangents start points are on the object to which this method applies, end points on the one passed as argument. /// Tangents are always returned in the same order: outer tangents before inner tangents, and for both, /// the tangent on the left side of the line from this circular arc center to the other one before the other one. /// </remarks> /// <param name="arc">The instance to which this method applies.</param> /// <param name="other">The CircularArc2d to which searched for tangents.</param> /// <param name="flags">An enum value specifying which type of tangent is returned.</param> /// <returns>An array of LineSegment2d representing the tangents (maybe 2 or 4) or null if there is none.</returns> public static LineSegment2d[] GetTangentsTo(this CircularArc2d arc, CircularArc2d other, TangentType flags) { // check if a circle is inside the other double dist = arc.Center.GetDistanceTo(other.Center); if (dist - Math.Abs(arc.Radius - other.Radius) <= Tolerance.Global.EqualPoint) return null; // check if circles overlap bool overlap = arc.Radius + other.Radius >= dist; if (overlap && flags == TangentType.Inner) return null; CircularArc2d tmp1, tmp2; Point2d[] inters; Vector2d vec1, vec2, vec = other.Center - arc.Center; int i, j; LineSegment2d[] result = new LineSegment2d[(int)flags == 3 && !overlap ? 4 : 2]; // outer tangents if ((flags & TangentType.Outer) > 0) { if (arc.Radius == other.Radius) { Line2d perp = new Line2d(arc.Center, vec.GetPerpendicularVector()); inters = arc.IntersectWith(perp); if (inters == null) return null; vec1 = (inters[0] - arc.Center).GetNormal(); vec2 = (inters[1] - arc.Center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1; j = i ^ 1; result[i] = new LineSegment2d(inters[0], inters[0] + vec); result[j] = new LineSegment2d(inters[1], inters[1] + vec); } else { Point2d center = arc.Radius < other.Radius ? other.Center : arc.Center; tmp1 = new CircularArc2d(center, Math.Abs(arc.Radius - other.Radius)); tmp2 = new CircularArc2d(arc.Center + vec / 2.0, dist / 2.0); inters = tmp1.IntersectWith(tmp2); if (inters == null) return null; vec1 = (inters[0] - center).GetNormal(); vec2 = (inters[1] - center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 0 : 1; j = i ^ 1; result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1 * other.Radius); result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2 * other.Radius); } } // inner tangents if ((flags & TangentType.Inner) > 0 && !overlap) { double ratio = (arc.Radius / (arc.Radius + other.Radius)) / 2.0; tmp1 = new CircularArc2d(arc.Center + vec * ratio, dist * ratio); inters = arc.IntersectWith(tmp1); if (inters == null) return null; vec1 = (inters[0] - arc.Center).GetNormal(); vec2 = (inters[1] - arc.Center).GetNormal(); i = vec.X * vec1.Y - vec.Y - vec1.X > 0 ? 2 : 3; j = i == 2 ? 3 : 2; result[i] = new LineSegment2d(arc.Center + vec1 * arc.Radius, other.Center + vec1.Negate() * other.Radius); result[j] = new LineSegment2d(arc.Center + vec2 * arc.Radius, other.Center + vec2.Negate() * other.Radius); } return result; }
public void Add(Line2d e) { Lines2d.Add(e); }
private bool GetUaUb(Line2d line1, Line2d line2, out float ua, out float ub) { ua = 0.0f; ub = 0.0f; // denominator var a = line1.Point1.Y - line1.Point0.Y; var d = line1.Point1.X - line1.Point0.X; var b = line2.Point0.X - line2.Point1.X; var c = line2.Point0.Y - line2.Point1.Y; var e = line2.Point0.X - line1.Point0.X; var f = line2.Point0.Y - line1.Point0.Y; var z = a * b - c * d; // numerator 1 var ca = a * e - f * d; // numerator 2 var cb = f * b - c * e; if (z == 0.0f) return false; ua = ca / z; ub = cb / z; return true; }
// The point of intersection of two segments private bool CollisionSegments(Line2d line1, Line2d line2, out Vector2 point) { point = Vector2.Zero; float ua, ub; if (!GetUaUb(line1, line2, out ua, out ub)) return false; if ((0.0f < ua) && (ua < 1.0f) && (0.0f < ub) && (ub < 1.0f)) { point.X = line1.Point0.X + (line1.Point1.X - line1.Point0.X) * ub; point.Y = line1.Point0.Y + (line1.Point1.Y - line1.Point0.Y) * ub; return true; } return false; }
public void Remove(Line2d e) { Lines2d.Remove(e); }