private Line2D m_line = new Line2D(); // geometry line to draw #endregion Fields #region Constructors /// <summary> /// constructor /// </summary> /// <param name="line"></param> public LineSketch(Line2D line) { m_line = line; m_boundingBox = line.BoundingBox; m_pen.Color = System.Drawing.Color.DarkGreen; m_pen.Width = 1f; }
/// <summary> /// generate a Line2D instance using a Line's data /// </summary> /// <param name="line">where new Line2D get data</param> /// <returns>new Line2D</returns> private static Line2D GetLine2D(Line line) { Line2D result = new Line2D(); result.StartPnt = new PointF((float)line.get_EndPoint(0).X, (float)line.get_EndPoint(0).Y); result.EndPnt = new PointF((float)line.get_EndPoint(1).X, (float)line.get_EndPoint(1).Y); return result; }
/// <summary> /// find the intersection points of two segments /// </summary> /// <param name="line0">first line</param> /// <param name="line1">second line</param> /// <param name="intersectPnt">0, 1 or 2 intersection points</param> /// <returns>number of intersection points; 0, 1, or 2</returns> public static int FindIntersection(Line2D line0, Line2D line1, ref PointF[] intersectPnt) { // segments p0 + s * d0 for s in [0, 0], p1 + t * d1 for t in [0, 1] PointF p0 = line0.StartPnt; PointF d0 = MathUtil.Multiply(line0.Length, line0.Normal); PointF p1 = line1.StartPnt; PointF d1 = MathUtil.Multiply(line1.Length, line1.Normal); PointF E = MathUtil.Subtract(p1, p0); float kross = d0.X * d1.Y - d0.Y * d1.X; float sqrKross = kross * kross; float sqrLen0 = d0.X * d0.X + d0.Y * d0.Y; float sqrLen1 = d1.X * d1.X + d1.Y * d1.Y; // lines of the segments are not parallel if (sqrKross > MathUtil.Float_Epsilon * sqrLen0 * sqrLen1) { float s = (E.X * d1.Y - E.Y * d1.X) / kross; if (s < 0 || s > 1) { // intersection of lines is not point on segment p0 + s * d0 return 0; } float t = (E.X * d0.Y - E.Y * d0.X) / kross; if (t < 0 || t > 1) { // intersection of lines is not a point on segment p1 + t * d1 return 0; } // intersection of lines is a point on each segment intersectPnt[0] = MathUtil.Add(p0, MathUtil.Multiply(s, d0)); return 1; } // lines of the segments are paralled float sqrLenE = E.X * E.X + E.Y * E.Y; float kross2 = E.X * d0.Y - E.Y * d0.X; float sqrKross2 = kross2 * kross2; if (sqrKross2 > MathUtil.Float_Epsilon * sqrLen0 * sqrLenE) { // lines of the segments are different return 0; } // lines of the segments are the same. need to test for overlap of segments float s0 = MathUtil.Dot(d0, E) / sqrLen0; float s1 = s0 + MathUtil.Dot(d0, d1) / sqrLen0; float smin = MathUtil.GetMin(s0, s1); float smax = MathUtil.GetMax(s0, s1); float[] w = new float[2]; int imax = MathUtil.FindIntersection(0.0f, 1.0f, smin, smax, ref w); for (int i = 0; i < imax; i++) { intersectPnt[i] = MathUtil.Add(p0, MathUtil.Multiply(w[i], d0)); } return imax; }
/// <summary> /// creates an instance of the GeometryLine class that is identical to the current GeometryLine /// </summary> /// <returns>created GeometryLine</returns> public Line2D Clone() { Line2D cloned = new Line2D(m_startPnt, m_endPnt); return cloned; }
/// <summary> /// find the number of intersection points for two segments /// </summary> /// <param name="line0">first line</param> /// <param name="line1">second line</param> /// <returns>number of intersection points; 0, 1, or 2</returns> public static int FindIntersection(Line2D line0, Line2D line1) { PointF[] intersectPnt = new PointF[2]; return FindIntersection(line0, line1, ref intersectPnt); }
/// <summary> /// sorted lines end to end to make a closed loop profile /// if input lines can't make a profile, null will return /// </summary> /// <param name="originLines">lines to be sorted</param> /// <returns>sorted lines which can make a closed loop profile</returns> public static List <Line> SortLines(List <Line> originLines) { // at least 3 lines to form the profile if (originLines.Count < 3) { return(null); } List <Line> lines = new List <Line>(originLines); List <Line> result = new List <Line>(); // sorted line end to end in order result.Add(lines[0]); Autodesk.Revit.DB.XYZ intersectPnt = lines[0].GetEndPoint(1); lines[0] = null; for (int i = 0; i < lines.Count; i++) { for (int j = 1; j < lines.Count; j++) { if (null == lines[j]) { continue; } if (CompareXYZ(lines[j].GetEndPoint(0), intersectPnt)) { result.Add(lines[j]); intersectPnt = lines[j].GetEndPoint(1); lines[j] = null; break; } else if (CompareXYZ(lines[j].GetEndPoint(1), intersectPnt)) { Autodesk.Revit.DB.XYZ startPnt = lines[j].GetEndPoint(1); Autodesk.Revit.DB.XYZ endPnt = lines[j].GetEndPoint(0); lines[j] = null; Line inversedLine = Line.CreateBound(startPnt, endPnt); result.Add(inversedLine); intersectPnt = inversedLine.GetEndPoint(1); break; } } } // there is line doesn't included in the closed loop if (result.Count != lines.Count) { return(null); } // the last point in the sorted loop is same to the firs point if (!CompareXYZ(intersectPnt, result[0].GetEndPoint(0))) { return(null); } // make sure there is only one closed region enclosed by the closed loop for (int i = 0; i < result.Count - 2; i++) { for (int j = i + 2; j < result.Count; j++) { if (i == 0 && j == (result.Count - 1)) { continue; } Line2D line1 = ConvertTo2DLine(result[i]); Line2D line2 = ConvertTo2DLine(result[j]); int count = Line2D.FindIntersection(line1, line2); // line shouldn't intersect with lines which not adjoin to it if (count > 0) { return(null); } } } return(result); }
/// <summary> /// find the intersection points of two segments /// </summary> /// <param name="line0">first line</param> /// <param name="line1">second line</param> /// <param name="intersectPnt">0, 1 or 2 intersection points</param> /// <returns>number of intersection points; 0, 1, or 2</returns> public static int FindIntersection(Line2D line0, Line2D line1, ref PointF[] intersectPnt) { // segments p0 + s * d0 for s in [0, 0], p1 + t * d1 for t in [0, 1] PointF p0 = line0.StartPnt; PointF d0 = MathUtil.Multiply(line0.Length, line0.Normal); PointF p1 = line1.StartPnt; PointF d1 = MathUtil.Multiply(line1.Length, line1.Normal); PointF E = MathUtil.Subtract(p1, p0); float kross = d0.X * d1.Y - d0.Y * d1.X; float sqrKross = kross * kross; float sqrLen0 = d0.X * d0.X + d0.Y * d0.Y; float sqrLen1 = d1.X * d1.X + d1.Y * d1.Y; // lines of the segments are not parallel if (sqrKross > MathUtil.Float_Epsilon * sqrLen0 * sqrLen1) { float s = (E.X * d1.Y - E.Y * d1.X) / kross; if (s < 0 || s > 1) { // intersection of lines is not point on segment p0 + s * d0 return(0); } float t = (E.X * d0.Y - E.Y * d0.X) / kross; if (t < 0 || t > 1) { // intersection of lines is not a point on segment p1 + t * d1 return(0); } // intersection of lines is a point on each segment intersectPnt[0] = MathUtil.Add(p0, MathUtil.Multiply(s, d0)); return(1); } // lines of the segments are paralled float sqrLenE = E.X * E.X + E.Y * E.Y; float kross2 = E.X * d0.Y - E.Y * d0.X; float sqrKross2 = kross2 * kross2; if (sqrKross2 > MathUtil.Float_Epsilon * sqrLen0 * sqrLenE) { // lines of the segments are different return(0); } // lines of the segments are the same. need to test for overlap of segments float s0 = MathUtil.Dot(d0, E) / sqrLen0; float s1 = s0 + MathUtil.Dot(d0, d1) / sqrLen0; float smin = MathUtil.GetMin(s0, s1); float smax = MathUtil.GetMax(s0, s1); float[] w = new float[2]; int imax = MathUtil.FindIntersection(0.0f, 1.0f, smin, smax, ref w); for (int i = 0; i < imax; i++) { intersectPnt[i] = MathUtil.Add(p0, MathUtil.Multiply(w[i], d0)); } return(imax); }
/// <summary> /// find the number of intersection points for two segments /// </summary> /// <param name="line0">first line</param> /// <param name="line1">second line</param> /// <returns>number of intersection points; 0, 1, or 2</returns> public static int FindIntersection(Line2D line0, Line2D line1) { PointF[] intersectPnt = new PointF[2]; return(FindIntersection(line0, line1, ref intersectPnt)); }
/// <summary> /// creates an instance of the GeometryLine class that is identical to the current GeometryLine /// </summary> /// <returns>created GeometryLine</returns> public Line2D Clone() { Line2D cloned = new Line2D(m_startPnt, m_endPnt); return(cloned); }