public static bool SegmentToAboveArc(Segment seg, Arc arcAbove, ref double distance) { bool success = false; distance = double.MaxValue; List<Segment> listArc = arcAbove.Explode(20); foreach (Segment segArc in listArc) { double dist = 0.0f; if (PointToAboveSegment(seg.P0, segArc, ref dist) && dist > 0) { distance = System.Math.Min(distance, dist); success = true; } if (PointToAboveSegment(seg.P1, segArc, ref dist) && dist > 0) { distance = System.Math.Min(distance, dist); success = true; } if (PointToAboveSegment(segArc.P0, seg, ref dist) && dist < 0) { distance = System.Math.Min(distance, -dist); success = true; } if (PointToAboveSegment(segArc.P1, seg, ref dist) && dist < 0) { distance = System.Math.Min(distance, -dist); success = true; } } return success; }
public static bool PointToAboveSegment(Vector2D p, Segment seg, ref double distance) { double xMin = System.Math.Min(seg.P0.X, seg.P1.X); double xMax = System.Math.Max(seg.P0.X, seg.P1.X); if (p.X < xMin - MathFunctions.EpsilonF || p.X > xMax + MathFunctions.EpsilonF) return false; else { double yMin = System.Math.Min(seg.P0.Y, seg.P1.Y); double yMax = System.Math.Max(seg.P0.Y, seg.P1.Y); if (System.Math.Abs(seg.P1.X - seg.P0.X) < MathFunctions.EpsilonF) { if (p.Y < yMin) distance = yMin - p.Y; else if (p.Y > yMax) distance = yMax - p.Y; else distance = 0.0f; } else distance = seg.P0.Y + (p.X - seg.P0.X) * (seg.P1.Y - seg.P0.Y) / (seg.P1.X - seg.P0.X) - p.Y; return true; } }
public static bool SegmentToAboveSegment(Segment seg, Segment segAbove, ref double distance) { bool success = false; distance = double.MaxValue; double dist = 0.0; if (PointToAboveSegment(seg.P0, segAbove, ref dist) && dist >= 0.0) { distance = System.Math.Min(distance, dist); success = true; } if (PointToAboveSegment(seg.P1, segAbove, ref dist) && dist >= 0.0) { distance = System.Math.Min(distance, dist); success = true; } if (PointToAboveSegment(segAbove.P0, seg, ref dist) && dist <= 0.0) { distance = System.Math.Min(distance, -dist); success = true; } if (PointToAboveSegment(segAbove.P1, seg, ref dist) && dist <= 0.0) { distance = System.Math.Min(distance, -dist); success = true; } return success; }
private static void TestArcToAboveSegment() { Arc arc = new Arc(Vector2D.Zero, 1.0f, -45.0f, -135.0f); Segment seg = new Segment(new Vector2D(-10.0f, 10.0f), new Vector2D(10.0f, 10.0f)); double distance = 0.0; VerticalDistance.ArcToAboveSegment(arc, seg, ref distance); Console.WriteLine(string.Format("ArcToAboveSegment = {0}", distance)); }
/// <summary> /// Calculates the squared distance between a point and a segment. /// </summary> /// <param name="point">A <see cref="Vector2D"/> instance.</param> /// <param name="segment">A <see cref="Segment"/> instance.</param> /// <returns>The squared distance between the point and the segment.</returns> public static double SquaredDistance(Vector2D point, Segment segment) { Vector2D D = segment.P1 - segment.P0; Vector2D diffPointP0 = point - segment.P0; double t = Vector2D.DotProduct(D, diffPointP0); if (t <= 0) { // segment.P0 is the closest to point. return Vector2D.DotProduct(diffPointP0, diffPointP0); } double DdD = Vector2D.DotProduct(D, D); if (t >= DdD) { // segment.P1 is the closest to point. Vector2D diffPointP1 = point - segment.P1; return Vector2D.DotProduct(diffPointP1, diffPointP1); } // Closest point is inside the segment. return Vector2D.DotProduct(diffPointP0, diffPointP0) - t * t / DdD; }
public static bool IntersectLines(Segment s0, Segment s1, out Intersection2D interObj) { // (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy) //r = ----------------------------- (eqn 1) // (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) // (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) //s = ----------------------------- (eqn 2) // (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) double den = (s0.P1.X - s0.P0.X) * (s1.P1.Y - s1.P0.Y) - (s0.P1.Y - s0.P0.Y) * (s1.P1.X - s1.P0.X); double r = (s0.P0.Y - s1.P0.Y) * (s1.P1.X - s1.P0.X) - (s0.P0.X - s1.P0.X) * (s1.P1.Y - s1.P0.Y); double s = (s0.P0.Y - s1.P0.Y) * (s0.P1.X - s0.P0.X) - (s0.P0.X - s1.P0.X) * (s0.P1.Y - s0.P0.Y); // If the denominator in eqn 1 is zero, AB & CD are parallel if (System.Math.Abs(den) > MathFunctions.EpsilonF) { r /= den; s /= den; // Let P be the position vector of the intersection point, then // P=A+r(B-A) interObj = new Intersection2D(new Vector2D(s0.P0 + r * (s0.P1 - s0.P0))); return true; } else { // If the numerator in eqn 1 is also zero, AB & CD are collinear. if (System.Math.Abs(r) < MathFunctions.EpsilonF) { } else { } } interObj = new Intersection2D(); return false; }
// segment intersection public Intersection2D(Segment seg) { _iType = IntersectionType.I2D_SEGMENT; _seg = seg; }
public static bool Intersect(Segment s0, Segment s1, out Intersection2D interObj) { // (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy) //r = ----------------------------- (eqn 1) // (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) // (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) //s = ----------------------------- (eqn 2) // (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) double den = (s0.P1.X - s0.P0.X) * (s1.P1.Y - s1.P0.Y) - (s0.P1.Y - s0.P0.Y) * (s1.P1.X - s1.P0.X); double r = (s0.P0.Y - s1.P0.Y) * (s1.P1.X - s1.P0.X) - (s0.P0.X - s1.P0.X) * (s1.P1.Y - s1.P0.Y); double s = (s0.P0.Y - s1.P0.Y) * (s0.P1.X - s0.P0.X) - (s0.P0.X - s1.P0.X) * (s0.P1.Y - s0.P0.Y); // If the denominator in eqn 1 is zero, AB & CD are parallel if (System.Math.Abs(den) < MathFunctions.EpsilonF) { // If the numerator in eqn 1 is also zero, AB & CD are collinear. if (System.Math.Abs(r) < MathFunctions.EpsilonF) { Interval i0 = new Interval(Interval.Type.Closed, System.Math.Min(s0.P0.X, s0.P1.X), System.Math.Max(s0.P0.X, s0.P1.X)); Interval i1 = new Interval(Interval.Type.Closed, System.Math.Min(s1.P0.X, s1.P1.X), System.Math.Max(s1.P0.X, s1.P1.X)); // check if interval overlaps if ((i0.Max < i1.Min) || (i1.Max < i0.Min)) { interObj = new Intersection2D(); return false; } else { Interval i2 = new Interval(Interval.Type.Closed, System.Math.Max(i0.Min, i1.Min), System.Math.Min(i0.Max, i1.Max)); interObj = new Intersection2D(new Segment()); return true; } } else { interObj = new Intersection2D(); return false; } } else { r /= den; s /= den; // Let P be the position vector of the intersection point, then // P=A+r(B-A) if (0 <= r && r <= 1 && 0 <= s && s <= 1) { interObj = new Intersection2D(new Vector2D(s0.P0+r*(s0.P1-s0.P0))); return true; } } interObj = new Intersection2D(); return false; }
/// <summary> /// /// </summary> /// <param name="factory"></param> public override void ProcessFactory(PicFactory factory) { // will only work with 2 segments if (null == _picSeg0 || null == _picSeg1) throw new NotImplementedException("Only segment entities are supported"); // get inner segments Segment seg0 = new Segment(_picSeg0.Pt0, _picSeg0.Pt1); Segment seg1 = new Segment(_picSeg1.Pt0, _picSeg1.Pt1); // find line intersection and extend segments so that they intersect Intersection2D interobj; if (!IntersectMethods.IntersectLines(seg0, seg1, out interobj) || interobj == null || interobj.Type != Intersection2D.IntersectionType.I2D_POINT) return; Vector2D ptExt = (Vector2D)interobj.Result; seg0 = extendSegment(seg0, ptExt); seg1 = extendSegment(seg1, ptExt); // create parallel segments Segment seg00, seg01; getParalleleSegments(seg0, _radius, out seg00, out seg01); Segment seg10, seg11; getParalleleSegments(seg1, _radius, out seg10, out seg11); // compute intersection if (IntersectMethods.Intersect(seg00, seg10, out interobj)) { } else if (IntersectMethods.Intersect(seg00, seg11, out interobj)) { } else if (IntersectMethods.Intersect(seg01, seg10, out interobj)) { } else if (IntersectMethods.Intersect(seg01, seg11, out interobj)) { } if (interobj == null || interobj.Type != Intersection2D.IntersectionType.I2D_POINT) return; Vector2D ptCenter = (Vector2D)interobj.Result; // get intersection of normal with seg0 if (IntersectMethods.Intersect(seg0, new Segment(ptCenter, ptCenter + new Vector2D(-(seg0.P1 - seg0.P0).Y, (seg0.P1 - seg0.P0).X)), out interobj)) { } else if (IntersectMethods.Intersect(seg0, new Segment(ptCenter, ptCenter + new Vector2D((seg0.P1 - seg0.P0).Y, -(seg0.P1 - seg0.P0).X)), out interobj)) { } else return; if (interobj == null && interobj.Type != Intersection2D.IntersectionType.I2D_POINT) return; Vector2D pt0 = (Vector2D)interobj.Result; if (IntersectMethods.Intersect(seg1, new Segment(ptCenter, ptCenter + new Vector2D(-(seg1.P1 - seg1.P0).Y, (seg1.P1 - seg1.P0).X)), out interobj)) { } else if (IntersectMethods.Intersect(seg1, new Segment(ptCenter, ptCenter + new Vector2D((seg1.P1 - seg1.P0).Y, -(seg1.P1 - seg1.P0).X)), out interobj)) { } else return; if (interobj == null && interobj.Type != Intersection2D.IntersectionType.I2D_POINT) return; Vector2D pt1 = (Vector2D)interobj.Result; // intersection of 2D segments if (!IntersectMethods.Intersect(seg0, seg1, out interobj)) return; if (interobj == null && interobj.Type != Intersection2D.IntersectionType.I2D_POINT) return; Vector2D ptInter = (Vector2D)interobj.Result; // modify segments if ((seg0.P0 - ptInter).GetLength() < (seg0.P1 - ptInter).GetLength()) { _picSeg0.Pt0 = pt0; _picSeg0.Pt1 = seg0.P1; } else { _picSeg0.Pt0 = pt0; _picSeg0.Pt1 = seg0.P0; } if ((seg1.P0 - ptInter).GetLength() < (seg1.P1 - ptInter).GetLength()) { _picSeg1.Pt0 = pt1; _picSeg1.Pt1 = seg1.P1; } else { _picSeg1.Pt0 = pt1; _picSeg1.Pt1 = seg1.P0; } // create new arc of circle if (Vector2D.KrossProduct(pt0 - ptCenter, pt1 - ptCenter) > 0) // go from pt0 to pt1 factory.AddArc(_picSeg0.LineType, _picSeg0.Group, _picSeg0.Layer, ptCenter, pt0, pt1); else // from pt1 to pt0 factory.AddArc(_picSeg0.LineType, _picSeg0.Group, _picSeg0.Layer, ptCenter, pt1, pt0); }
/// <summary> /// get an extended segment using given point if it is not already on the segment /// </summary> /// <param name="segInit">initial segment</param> /// <param name="pt">point to use in order to extend segment</param> /// <returns>a segment which contains both the initial segment and the given point</returns> static private Segment extendSegment(Segment segInit, Vector2D pt) { Vector2D vecSeg = segInit.P1 - segInit.P0; double prod0 = Vector2D.DotProduct(segInit.P0 - pt, vecSeg); double prod1 = Vector2D.DotProduct(segInit.P1 - pt, vecSeg); if (prod0 > 0 && prod1 > 0) return new Segment(pt, segInit.P1); // extend segment on the P0 side else if (prod0 < 0 && prod1 < 0) return new Segment(pt, segInit.P0); // extend segment on the P1 side else return new Segment(segInit); // do not need to extend segment }
/// <summary> /// compute the two parallel segments at a certain distance /// </summary> /// <param name="segInit">initial segment</param> /// <param name="dist">distance</param> /// <param name="s0">first segment (out)</param> /// <param name="s1">second segment (out)</param> static private void getParalleleSegments(Segment segInit, double dist, out Segment s0, out Segment s1) { // get dir vector Vector2D vecDir = segInit.P1 - segInit.P0; vecDir /= vecDir.GetLength(); // vecNormal Vector2D vecNorm = new Vector2D(-vecDir.Y, vecDir.X); // compute segment Vector2D p00 = segInit.P0 + dist * vecNorm; s0 = new Segment(p00, p00 + segInit.P1 - segInit.P0); Vector2D p10 = segInit.P0 - dist * vecNorm; s1 = new Segment(p10, p10 + segInit.P1 - segInit.P0); }
public override void ProcessFactory(PicFactory factory) { // initialization _segList.Clear(); _box = new Box2D(); _area = 0.0; // build list of segments with entities that belongs to group factory.ProcessToolAllEntities(this); _box.AddMarginRatio(0.2); // exit if no of segments exceeds MAXSEG int maxSeg = Pic.Factory2D.Properties.Settings.Default.AreaMaxNoSegments; if (_segList.Count > maxSeg) throw new PicToolTooLongException(string.Format("No of segments exceeds {0}", maxSeg)); // compute actual step size uint iNoStep = (uint)(_box.Width / _stepSize); iNoStep = Math.Min(iNoStep, _iNoStepMax); double stepDefault = _box.Width / iNoStep; // compute area for (int i = 0; i < iNoStep; ++i) { double xh = _box.XMin + i * stepDefault; int nby = 1; double stepCurrent = stepDefault; List<double> tabyh = new List<double>(); tabyh.Add(double.MaxValue); bool bAgain = false; do { bAgain = false; stepCurrent = stepDefault; foreach (Segment segTemp in _segList) { Segment seg; if (segTemp.P0.X <= segTemp.P1.X) seg = segTemp; else seg = new Segment(segTemp.P1, segTemp.P0); if (xh >= seg.P0.X && xh <= seg.P1.X) { // cas intersections confondues if ((Math.Abs(xh - seg.P0.X) < 0.001) || (Math.Abs(seg.P1.X - xh) < 0.001)) { // restart loop from the beginning nby = 1; tabyh[0] = double.MaxValue; stepCurrent = 0.9 * stepDefault; xh -= stepDefault * 0.1; bAgain = true; break; } else { double yh = seg.P0.Y + (xh - seg.P0.X) * ((seg.P1.Y - seg.P0.Y) / (seg.P1.X - seg.P0.X)); tabyh.Add(yh); } } } } while (bAgain); tabyh.Sort(); nby = tabyh.Count; // increment area if (nby > 1 && (nby % 2 != 0)) { for (int l = 0; l < nby - 1; l += 2) { _area = _area + stepCurrent * (tabyh[l + 1] - tabyh[l]); } } } }
/// <summary> /// Calculates the distance between two segments. /// </summary> /// <param name="s0">A <see cref="Segment"/> instance.</param> /// <param name="s1">A <see cref="Segment"/> instance.</param> /// <returns>Returns the distance between two segments.</returns> public static float Distance(Segment s0, Segment s1) { throw new NotImplementedException(); }
/// <summary> /// Calculates the squared distance between a point and a segment. /// </summary> /// <param name="point">A <see cref="Vector2D"/> instance.</param> /// <param name="segment">A <see cref="Segment"/> instance.</param> /// <returns>The squared distance between the point and the segment.</returns> public static double Distance(Vector2D point, Segment segment) { return System.Math.Sqrt(SquaredDistance(point, segment)); }
/// <summary> /// Initializes a new instance of the <see cref="Segment"/> class using an existing <see cref="Segment"/> instance. /// </summary> /// <param name="segment">A <see cref="Segment"/> instance.</param> public Segment(Segment segment) { _p0 = segment.P0; _p1 = segment.P1; }
public static bool Intersect(Segment seg, Ray ray, out Intersection2D interObj) { // (Ay-Cy)(Dx-Cx)-(Ax-Cx)(Dy-Cy) //r = ----------------------------- (eqn 1) // (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) // (Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay) //s = ----------------------------- (eqn 2) // (Bx-Ax)(Dy-Cy)-(By-Ay)(Dx-Cx) double den = (seg.P1.X - seg.P0.X) * ray.Direction.Y - (seg.P1.Y - seg.P0.Y) * ray.Direction.X; double r = (seg.P0.Y - ray.Origin.Y) * ((ray.Origin + ray.Direction).X - ray.Origin.X) - (seg.P0.X - ray.Origin.X) * ((ray.Origin + ray.Direction).Y - ray.Origin.Y); // If the denominator in eqn 1 is zero, AB & CD are parallel if (System.Math.Abs(den) < MathFunctions.EpsilonF) { // If the numerator in eqn 1 is also zero, AB & CD are collinear. if (System.Math.Abs(r) < MathFunctions.EpsilonF) { interObj = new Intersection2D(new Segment(seg)); return true; } else { interObj = new Intersection2D(); return false; } } else { r /= den; // Let P be the position vector of the intersection point, then // P=A+r(B-A) if (0 <= r && r <= 1) { interObj = new Intersection2D(new Vector2D(seg.P0 + r * (seg.P1 - seg.P0))); return true; } } interObj = new Intersection2D(); return false; }