Пример #1
0
        /// <summary>
        /// Find the point of intersection of an arc and a line
        /// </summary>
        /// <param name="other">The line to find intersection with</param>
        /// <returns>[x, y] if applicable; [] otherwise</returns>
        private double[] ArcLineIntersection(LineSegment other)
        {
            double x1, x2, x3, y1, y2, y3, a, b, c, det, u, t;
            int    numof_int = 0;

            x1 = (double)other.StartPoint.X; y1 = (double)other.StartPoint.Y;
            x2 = (double)other.EndPoint.X; y2 = (double)other.EndPoint.Y;
            x3 = (double)centerPoint.X; y3 = (double)centerPoint.Y;

            a = Math.Pow(x2 - x1, 2.0) + Math.Pow(y2 - y1, 2.0);
            b = 2 * ((x2 - x1) * (x1 - x3) + (y2 - y1) * (y1 - y3));
            c = Math.Pow(x3, 2.0) + Math.Pow(y3, 2.0) + Math.Pow(x1, 2.0) + Math.Pow(y1, 2.0) - 2 * (x3 * x1 + y3 * y1) - Math.Pow(radius, 2.0);

            if (a == 0.0)
            {
                return(new double[0]);
            }

            det = Math.Pow(b, 2.0) - 4 * a * c;

            if (det < 0.0)
            {
                return(new double[0]);        //no intersection
            }
            else if (det == 0.0)              //one intersection
            {
                u = (-b) / 2.0 / a;
                if (u > (1 + INTERSECTION_TOLERANCE_PERCENTAGE) || u < (0 - INTERSECTION_TOLERANCE_PERCENTAGE))
                {
                    return(new double[0]);
                }

                float    x     = (float)(x1 + u * (x2 - x1));
                float    y     = (float)(y1 + u * (y2 - y1));
                double[] intPt = new double[] { x, y };

                double theta = Math.Atan2(intPt[1] - centerPoint.Y, intPt[0] - centerPoint.X) * 180 / Math.PI;

                double endAngle = startAngle + sweepAngle;

                if (sweepAngle > 0)
                {
                    t = (theta - startAngle) / (endAngle - startAngle);
                }
                else
                {
                    t = -(theta - startAngle) / (endAngle - startAngle);
                }
            }

            else             //two intersections
            {
                u = (-b - Math.Sqrt(det)) / 2.0 / a;

                if (!(u > (1 + INTERSECTION_TOLERANCE_PERCENTAGE) || u < (0 - INTERSECTION_TOLERANCE_PERCENTAGE)))
                {
                    //intP1.x = x1 + u * (x2 - x1);
                    //intP1.y = y1 + u * (y2 - y1);
                    numof_int++;
                }

                u = (-b + Math.Sqrt(det)) / 2.0 / a;

                if (!(u > (1 + INTERSECTION_TOLERANCE_PERCENTAGE) || u < (0 - INTERSECTION_TOLERANCE_PERCENTAGE)))
                {
                    //intP2.x = x1 + u * (x2 - x1);
                    //intP2.y = y1 + u * (y2 - y1);
                    numof_int++;
                    //if (numof_int == 1) intP1 = intP2;
                }
            }
            return(new double[2]);
        }
Пример #2
0
 private double[] lineIntersects(LineSegment other)
 {
     return(lineIntersects(other, 0.0d));
 }
Пример #3
0
 /// <summary>
 /// Near-intersection
 /// </summary>
 /// <param name="other"></param>
 /// <returns></returns>
 public double[] nearIntersection(LineSegment other)
 {
     return(lineIntersects(other, 25));
 }
Пример #4
0
        /// <summary>
        /// Takes a wire and returns the shape that is closest to the end of the wire
        /// along the line shooting off of the end.
        /// </summary>
        /// <param name="beginning">Which end we're looking at.</param>
        /// <param name="wire">The wire we're considering.</param>
        /// <param name="sketch">The sketch providing the context for the wire.</param>
        /// <returns>The shape that's closest to the tip of the wire.</returns>
        private Sketch.Shape findClosest(bool beginning, Sketch.Substroke wire, Sketch.Sketch sketch)
        {
            List <Sketch.Substroke> intersects = new List <Sketch.Substroke>();

            // One method of removing hooks (in situations where the substroke loops around to
            // get closer to its endpoint.
            List <Sketch.Point> points = Featurefy.Compute.DeHook(wire).PointsL;

            points.Sort();
            if (!beginning)
            {
                points.Reverse();
            }

            // First we will generate the line segments shooting off the endpoints of the wires.
            Sketch.LineSegment segment1;
            int count = 20;

            if (points.Count < 2 * count)
            {
                segment1 = new Sketch.LineSegment(points[0], points[points.Count - 1]);
            }
            else
            {
                segment1 = new Sketch.LineSegment(points.GetRange(0, count).ToArray());
            }

            Sketch.Substroke closestSubstroke         = null;
            Sketch.Substroke closestLinestroke        = null;
            double           closestSubstrokeDistance = Double.PositiveInfinity;
            double           closestLineDistance      = Double.PositiveInfinity;

            // Now, consider every substroke in the sketch.
            foreach (Sketch.Substroke substroke in sketch.SubstrokesL)
            {
                if (substroke.Id != wire.Id)
                {
                    // We want this stroke if it is close to the line shooting out of the end of the wire
                    // Or if it is close enough to the endpoint.
                    foreach (Sketch.Point point in substroke.Points)
                    {
                        double linedistance  = point.distance(segment1.getClosestPointOnLine(point));
                        double pointdistance = point.distance(points[0]);
                        if (pointdistance < closestSubstrokeDistance)
                        {
                            closestSubstrokeDistance = point.distance(points[0]);
                            closestSubstroke         = substroke;
                        }
                        if (2 * linedistance + pointdistance < closestLineDistance)
                        {
                            // We want to make sure it's on the correct side of the line.
                            Sketch.Point linepoint = segment1.getClosestPointOnLine(point);
                            if ((segment1.StartPoint.X < segment1.EndPoint.X && linepoint.X < segment1.StartPoint.X) ||
                                (segment1.StartPoint.X > segment1.EndPoint.X && linepoint.X > segment1.StartPoint.X))
                            {
                                closestLineDistance = 2 * linedistance + pointdistance;
                                closestLinestroke   = substroke;
                            }
                        }
                    }
                }
            }


            // Returning the right substroke:

            double thresholdLineDistance      = 50.0; // MAGIC NUMBER! A somewhat arbitrary number pulled out of the air.
            double thresholdSubstrokeDistance = 20.0; // MAGIC NUMBER! A somewhat arbitrary number pulled out of the air.

            // The threshold is stricter on substrokes that are nearby but
            // are not in the right direction

            // Substrokes that are close to the projected line get priority.
            if ((closestLineDistance < thresholdLineDistance) &&
                (closestLinestroke != null) &&
                (closestLinestroke.ParentShape != null))
            {
                return(closestLinestroke.ParentShape);
            }

            // If the Linestroke wasn't good enough, try the closest substroke.
            else if ((closestSubstrokeDistance < thresholdSubstrokeDistance) &&
                     (closestSubstroke != null) &&
                     (closestSubstroke.ParentShape != null))
            {
                return(closestSubstroke.ParentShape);
            }

            // We get here if none of the substrokes were close enough
            else
            {
                return(null);
            }


            //// Now we need to decide whether we want the closest substroke, or the one closest to the line...
            //if (closestLineDistance / 5 > closestSubstrokeDistance)
            //    if (closestSubstroke == null)
            //        return null;
            //    else
            //        return closestSubstroke.ParentShapes[0];
            //else
            //    if (closestLinestroke == null)
            //        return null;
            //    else
            //        return closestLinestroke.ParentShapes[0];
        }