示例#1
0
 /// <summary>
 /// Initialises a new polycurve
 /// </summary>
 /// <param name="curves"></param>
 public PolyCurve(IEnumerable <Curve> curves, GeometryAttributes attributes = null) : this(attributes)
 {
     foreach (Curve crv in curves)
     {
         SubCurves.Add(crv);
     }
 }
示例#2
0
        /// <summary>
        /// Automatically fillet any sharp corners between segments in the PolyCurve
        /// </summary>
        /// <param name="angleLimit">The smallest permissible angle</param>
        /// <param name="filletLength">The smallest permissible length of the added fillet curve</param>
        public void FilletSharpCorners(Angle angleLimit, double filletLength)
        {
            int iMax = SubCurves.Count - 1;

            if (Closed)
            {
                iMax += 1;
            }
            for (int i = 0; i < iMax; i++)
            {
                Curve crvA = SubCurves.GetWrapped(i);
                //TODO: Recursively fillet polys
                Curve crvB = SubCurves.GetWrapped(i + 1);

                Vector tA = crvA.TangentAt(1);
                Vector tB = crvB.TangentAt(0);

                Angle angle = (Math.PI - tA.AngleBetween(tB).Abs());

                if (angle < angleLimit)
                {
                    double cutBack = filletLength / (2 * Math.Sin(angle / 2));

                    if (crvA.Length > cutBack && crvB.Length > cutBack &&
                        crvA.TrimEnd(cutBack) && crvB.TrimStart(cutBack))
                    {
                        Line fillet = new Line(crvA.EndPoint, crvB.StartPoint);
                        SubCurves.Insert(i + 1, fillet);
                        i++;
                        iMax++;
                    }
                    //TODO: Deal with failed trims better
                }
            }
        }
示例#3
0
 /// <summary>
 /// Reverse the direction of this curve
 /// </summary>
 public override void Reverse()
 {
     foreach (var subCrv in SubCurves)
     {
         subCrv.Reverse();
     }
     SubCurves.Reverse();
 }
示例#4
0
 /// <summary>
 /// Add a new sub-curve to this PolyCurve.
 /// Note that to form a valid polycurve the new sub-curve *must*
 /// start at a point within tolerance of the end point of the
 /// last sub-curve.  If autoConnect is set to true, this condition
 /// will be checked for and a line segment automatically added to
 /// connect the curve ends if necessary.
 /// </summary>
 /// <param name="subCurve">The curve to add.</param>
 /// <param name="autoConnect">If true, a line segment will automatically be added between
 /// the end of the last curve and the start of the newly-added one to close
 /// any gap between them, if necessary.</param>
 public void Add(Curve subCurve, bool autoConnect)
 {
     if (autoConnect == true && SubCurves.Count > 0)
     {
         Vector endPt = SubCurves.Last().EndPoint;
         if (endPt.DistanceToSquared(subCurve.StartPoint) > (Tolerance.Distance * Tolerance.Distance))
         {
             //Out of tolerance; create a line:
             Add(new Line(endPt, subCurve.StartPoint));
         }
     }
     Add(subCurve);
 }
示例#5
0
 /// <summary>
 /// Add a new line segment to the end of this polycurve.
 /// The line will run from the end of the last subcurve in this polycurve
 /// to the specified point.
 /// This polycurve must contain at least one subcurve already in order for the start
 /// point to be determined.
 /// </summary>
 /// <param name="lineEnd">The end point of the new line segment.</param>
 /// <returns></returns>
 public Line AddLine(Vector lineEnd)
 {
     if (SubCurves.Count > 0)
     {
         Vector startPoint = SubCurves.Last().EndPoint;
         Line   result     = new Line(startPoint, lineEnd);
         Add(result);
         return(result);
     }
     else
     {
         return(null);
     }
 }
示例#6
0
 /// <summary>
 /// Add a new arc segment to the end of this polycurve.
 /// The arc will run from the end of the last subcurve in this polycurve
 /// to the specified point, following the specified tangent at its start.
 /// This polycurve must contain at least one subcurve already in order for the
 /// start point to be determined.
 /// </summary>
 /// <param name="endX">The x-coordinate of the end point of the new arc segement</param>
 /// <param name="endY">The y-coordinate of the end point of the new arc segement</param>
 /// <param name="endZ">The z-coordinate of the end point of the new arc segement</param>
 /// <returns></returns>
 public Curve AddArcTangent(Vector startTangent, Vector arcEnd)
 {
     if (SubCurves.Count > 0)
     {
         Curve  last    = SubCurves.Last();
         Vector startPt = last.EndPoint;
         Curve  result  = Arc.StartTangentEnd(startPt, startTangent, arcEnd);
         if (result != null)
         {
             Add(result);
         }
         return(result);
     }
     else
     {
         return(null);
     }
 }
示例#7
0
        /// <summary>
        /// Collapse any segments of this curve which have a length shorter than the
        /// value specified.  The end-points of the curve will be kept the same, but
        /// short polyline segments and polycurve subcurves will be removed and the
        /// adjacent curves adjusted accordingly.
        /// </summary>
        /// <param name="minLength">The length below which segments will be removed.</param>
        /// <returns>True if any segments were removed.</returns>
        public override bool CollapseShortSegments(double minLength)
        {
            bool removedAny = false;

            for (int i = 0; i < SubCurves.Count; i++)
            {
                if (SubCurves.Count > 1)
                {
                    var    subCrv   = SubCurves[i];
                    double sCLength = subCrv.Length;
                    if (sCLength < minLength)
                    {
                        if (!Closed && i == 0)
                        {
                            // Snap next to start
                            var nextCrv = SubCurves[1];
                            nextCrv.Start.Position = subCrv.StartPoint;
                        }
                        else if (!Closed && i == SubCurves.Count - 1)
                        {
                            // Snap prev to end
                            var prevCrv = SubCurves[i - 1];
                            prevCrv.End.Position = subCrv.EndPoint;
                        }
                        else
                        {
                            // Snap adjacent to mid-point
                            var    nextCrv = SubCurves.GetWrapped(i + 1);
                            var    prevCrv = SubCurves.GetWrapped(i - 1);
                            Vector midPt   = subCrv.PointAtLength(sCLength / 2);
                        }
                        SubCurves.RemoveAt(i);
                        i--;
                        removedAny = true;
                    }
                }
            }
            if (removedAny)
            {
                NotifyGeometryUpdated();
            }
            return(removedAny);
        }
示例#8
0
        /// <summary>
        /// Reduce the length of this curve from the end
        /// by the specified value
        /// </summary>
        /// <param name="length">The length to cut back from the curve end</param>
        /// <returns>True if successful, false if not.</returns>
        public override bool TrimEnd(double length)
        {
            bool   result = false;
            double l0     = 0;

            for (int i = 0; i < SubCurves.Count; i++)
            {
                Curve  subCrv    = SubCurves[SubCurves.Count - 1 - i];
                double crvLength = subCrv.Length;
                double l1        = l0 + crvLength;
                if (l1 > length)
                {
                    result = subCrv.TrimStart(length - l0);
                    for (int j = 0; j < i; j++)
                    {
                        SubCurves.RemoveAt(0);
                    }
                    break;
                }
            }

            return(result);
        }
示例#9
0
 /// <summary>
 /// Add a new sub-curve to this PolyCurve.
 /// Note that to form a valid polycurve the new sub-curve *must*
 /// start at a point within tolerance of the end point of the
 /// last sub-curve.
 /// </summary>
 /// <param name="subCurve">The curve to add.</param>
 public void Add(Curve subCurve)
 {
     SubCurves.Add(subCurve);
 }
示例#10
0
 /// <summary>
 /// Curve constructor.  Initialises a polycurve starting with the specifed curve
 /// </summary>
 /// <param name="curve"></param>
 public PolyCurve(Curve curve, GeometryAttributes attributes = null) : this(attributes)
 {
     SubCurves.Add(curve);
 }
示例#11
0
        /// <summary>
        /// Extract from this PolyCurve a chain of subcurves, starting with the
        /// longest and continuing to select the longest edge until no more can
        /// be added without adding an edge which is within an angle tolerance of
        /// an existing curve within the chain.
        /// </summary>
        /// <returns></returns>
        public PolyCurve ExtractLongCurveChain(Angle maxAngle)
        {
            Curve longest = SubCurves.GetLongest();

            if (longest != null)
            {
                var tangents = new List <Vector>();
                tangents.Add(longest.TangentAt(0.5));
                var  result  = new PolyCurve(longest);
                int  iL      = SubCurves.IndexOf(longest);
                int  i0      = iL - 1;
                int  i1      = iL + 1;
                bool closed  = Closed;
                bool tryPre  = closed || i0 >= 0;
                bool tryPost = closed || i1 < SubCurves.Count;
                while (tryPre || tryPost)
                {
                    Curve pre  = tryPre ? SubCurves.GetWrapped(i0, closed) : null;
                    Curve post = tryPost ? SubCurves.GetWrapped(i1, closed) : null;
                    if (post != null && (pre == null || post.Length > pre.Length))
                    {
                        Vector tang = post.TangentAt(0.5);
                        if (result.SubCurves.Contains(post.GUID) || tangents.MaximumAngleBetween(tang).Abs() > maxAngle)
                        {
                            tryPost = false;
                        }
                        else
                        {
                            result.SubCurves.Add(post);
                            tangents.Add(tang);
                            i1++;
                            if (!closed && i1 >= SubCurves.Count)
                            {
                                tryPost = false;
                            }
                        }
                    }
                    else if (pre != null)
                    {
                        Vector tang = pre.TangentAt(0.5);
                        if (result.SubCurves.Contains(pre.GUID) || tangents.MaximumAngleBetween(tang).Abs() > maxAngle)
                        {
                            tryPre = false;
                        }
                        else
                        {
                            result.SubCurves.Insert(0, pre);
                            tangents.Add(tang);
                            i0--;
                            if (!closed && i0 < 0)
                            {
                                tryPre = false;
                            }
                        }
                    }
                    else
                    {
                        tryPre  = false;
                        tryPost = false;
                    }
                }
                return(result);
            }
            return(null);
        }