Esempio n. 1
0
        /// <summary>
        /// Generates a rectangular polycurve on the XY plane centred on the origin
        /// </summary>
        /// <param name="depth">The depth of the rectangle</param>
        /// <param name="width">The width of the rectangle</param>
        /// <returns></returns>
        public static PolyCurve Rectangle(double depth, double width, double cornerRadius = 0.0)
        {
            cornerRadius = Math.Max(cornerRadius, 0.0);
            double x  = width / 2;
            double y  = depth / 2;
            double x2 = Math.Max(x - cornerRadius, 0.0);
            double y2 = Math.Max(y - cornerRadius, 0.0);

            PolyCurve result = new PolyCurve(new Line(x2, y, -x2, y));

            if (cornerRadius > 0)
            {
                result.AddArcTangent(new Vector(-1, 0), new Vector(-x, y2));
            }
            result.AddLine(-x, -y2);
            if (cornerRadius > 0)
            {
                result.AddArcTangent(new Vector(0, -1), new Vector(-x2, -y));
            }
            result.AddLine(x2, -y);
            if (cornerRadius > 0)
            {
                result.AddArcTangent(new Vector(1, 0), new Vector(x, -y2));
            }
            result.AddLine(x, y2);
            if (cornerRadius > 0)
            {
                result.AddArcTangent(new Vector(0, 1), new Vector(x2, y));
            }

            return(result);
        }
Esempio n. 2
0
        /// <summary>
        /// Generates a trapezoid polygon on the XY plane with the midpoint of each edge
        /// centred on the origin and with a different top and bottom width.
        /// </summary>
        /// <param name="depth">The depth of the trapezoid</param>
        /// <param name="topWidth">The width of the top of the trapezoid</param>
        /// <param name="baseWidth">The width of the base of the trapezoid</param>
        /// <returns></returns>
        public static PolyCurve Trapezoid(double depth, double topWidth, double baseWidth)
        {
            double xT = topWidth / 2;
            double xB = baseWidth / 2;
            double y  = depth / 2;

            PolyCurve result = new PolyCurve(new Line(xT, y, -xT, y));

            result.AddLine(-xB, -y);
            result.AddLine(xB, -y);
            result.AddLine(xT, y);

            return(result);
        }
Esempio n. 3
0
        /// <summary>
        /// Split this region into two (or more) sub-regions along a straight line
        /// </summary>
        /// <param name="splitPt">A point on the splitting line</param>
        /// <param name="splitDir">The direction of the line</param>
        /// <param name="splitWidth">Optional.  The width of the split.</param>
        /// <returns>The resultant list of regions.  If the line does not bisect
        /// this region and the region could not be split, this collection will contain
        /// only the original region.</returns>
        public IList <PlanarRegion> SplitByLineXY(Vector splitPt, Vector splitDir, double splitWidth = 0)
        {
            var result    = new List <PlanarRegion>();
            var lineInts  = new List <double>();
            var outerInts = Intersect.CurveLineXY(Perimeter, splitPt, splitDir, null, 0, 1, false, lineInts);

            if (outerInts.Count > 1)
            {
                // Sort intersections by position along curve:
                var sortedInts = new SortedList <double, double>(outerInts.Count);
                for (int i = 0; i < outerInts.Count; i++)
                {
                    sortedInts.Add(outerInts[i], lineInts[i]);
                }

                outerInts = sortedInts.Keys.ToList();
                lineInts  = sortedInts.Values.ToList();
                int offset = lineInts.IndexOfMin();
                outerInts.Shift(offset);
                lineInts.Shift(offset);

                // Create segments data structure
                var segments = new List <PerimeterSegment>(outerInts.Count - 1);
                for (int i = 0; i < outerInts.Count; i++)
                {
                    double t0      = outerInts[i];
                    double t1      = outerInts.GetWrapped(i + 1);
                    double tC0     = lineInts[i];
                    double tC1     = lineInts.GetWrapped(i + 1);
                    var    segment = new PerimeterSegment(Perimeter, t0, t1, tC0, tC1);
                    segments.Add(segment);
                }

                //TODO: void intersections

                bool backwards = true;
                while (segments.Count > 0)
                {
                    var offsets = new List <double>();
                    PerimeterSegment segment = segments.First();

                    PolyCurve newPerimeter = segment.Extract().ToPolyCurve();
                    for (int i = 0; i < newPerimeter.SegmentCount; i++)
                    {
                        offsets.Add(0);
                    }
                    PerimeterSegment nextSegment = FindNextPerimeterSegment(segments, segment.CutterDomain.End, backwards);
                    while (nextSegment != null && nextSegment != segment)
                    {
                        Curve nextCurve = nextSegment.Extract();
                        newPerimeter.AddLine(nextCurve.StartPoint);
                        offsets.Add(splitWidth / 2);
                        newPerimeter.Add(nextCurve);
                        for (int i = 0; i < nextCurve.SegmentCount; i++)
                        {
                            offsets.Add(0);
                        }
                        segments.Remove(nextSegment);
                        nextSegment = FindNextPerimeterSegment(segments, nextSegment.CutterDomain.End, backwards);
                    }
                    segments.RemoveAt(0);
                    if (!newPerimeter.Closed)
                    {
                        /*if (splitWidth > 0)
                         * {
                         *  // Temporary bodge to get rid of 'blades' at ends of split
                         *  Vector endToEnd = (newPerimeter.StartPoint - newPerimeter.EndPoint).Unitize();
                         *  var line = new Line(
                         *      newPerimeter.EndPoint - endToEnd * splitWidth / 4,
                         *      newPerimeter.StartPoint + endToEnd * splitWidth / 4);
                         *  newPerimeter.AddLine(line.StartPoint);
                         *  offsets.Add(0);
                         *  newPerimeter.Add(line);
                         *  offsets.Add(splitWidth / 2);
                         *  newPerimeter.Close();
                         *  offsets.Add(0);
                         * }
                         * else
                         * {*/
                        newPerimeter.Close();
                        offsets.Add(splitWidth / 2);
                        //}
                    }
                    backwards = !backwards;

                    if (splitWidth > 0)
                    {
                        var newNewPerimeter = newPerimeter.OffsetInwards(offsets);
                        // Check offset has not inverted perimeter:
                        // TODO: Do this automatically when offsetting?
                        if (newNewPerimeter != null && newNewPerimeter.IsClockwiseXY() == newPerimeter.IsClockwiseXY())
                        {
                            newPerimeter = newNewPerimeter.ToPolyCurve();
                        }
                        else
                        {
                            newPerimeter = null;
                        }
                    }

                    if (newPerimeter != null)
                    {
                        result.Add(new PlanarRegion(newPerimeter, Attributes?.Duplicate()));
                    }
                }

                // OLD VERSION:

                /*for (int i = 0; i < outerInts.Count; i++)
                 * {
                 *  double t0 = outerInts[i];
                 *  double t1 = outerInts.GetWrapped(i + 1);
                 *  Curve newPerimeter = Perimeter.Extract(new Interval(t0, t1))?.ToPolyCurve();
                 *  //TODO: Cut through and include voids
                 *  if (!newPerimeter.Closed)
                 *  {
                 *      ((PolyCurve)newPerimeter).Close();
                 *      if (splitWidth > 0)
                 *      {
                 *          var offsets = new double[newPerimeter.SegmentCount];
                 *          offsets[offsets.Length - 1] = splitWidth / 2;
                 *          var newNewPerimeter = newPerimeter.OffsetInwards(offsets);
                 *          // Check offset has not inverted perimeter:
                 *          // TODO: Do this automatically when offsetting?
                 *          if (newNewPerimeter != null && newNewPerimeter.IsClockwiseXY() == newPerimeter.IsClockwiseXY())
                 *          {
                 *              newPerimeter = newNewPerimeter;
                 *          }
                 *          else newPerimeter = null;
                 *      }
                 *  }
                 *  if (newPerimeter != null) result.Add(new PlanarRegion(newPerimeter, Attributes?.Duplicate()));
                 * }*/
            }
            else
            {
                result.Add(this); //Return the original
            }
            return(result);
        }