Пример #1
0
        internal static bool Intersects(Ray ray, solids.Face face, out Vector3 result)
        {
            var edges = face.Outer.Edges;
            var a     = edges[0].Vertex.Point;
            var b     = edges[1].Vertex.Point;
            var c     = edges[2].Vertex.Point;
            var plane = new Plane(a, b, c);

            if (ray.Intersects(plane, out Vector3 intersection))
            {
                var boundaryPolygon      = face.Outer.ToPolygon();
                var transformToPolygon   = new Transform(plane.Origin, plane.Normal);
                var transformFromPolygon = new Transform(transformToPolygon);
                transformFromPolygon.Invert();
                var transformedPolygon      = transformFromPolygon.OfPolygon(boundaryPolygon);
                var transformedIntersection = transformFromPolygon.OfVector(intersection);
                if (transformedPolygon.Contains(transformedIntersection) || transformedPolygon.Touches(transformedIntersection))
                {
                    result = intersection;
                    return(true);
                }
            }
            result = default(Vector3);
            return(false);
        }
Пример #2
0
        /// <summary>
        /// Construct a solid by sweeping a face in a direction.
        /// </summary>
        /// <param name="perimeter">The perimeter of the face to sweep.</param>
        /// <param name="holes">The holes of the face to sweep.</param>
        /// <param name="direction">The direction in which to sweep.</param>
        /// <param name="distance">The distance to sweep.</param>
        /// <param name="bothSides">Should the sweep start offset by direction distance/2? </param>
        /// <param name="rotation">An optional rotation in degrees of the perimeter around the direction vector.</param>
        /// <returns>A solid.</returns>
        public static Solid SweepFace(Polygon perimeter,
                                      IList <Polygon> holes,
                                      Vector3 direction,
                                      double distance,
                                      bool bothSides  = false,
                                      double rotation = 0.0)
        {
            // We do a difference of the polygons
            // to get the clipped shape. This will fail in interesting
            // ways if the clip creates two islands.
            // if(holes != null)
            // {
            //     var newPerimeter = perimeter.Difference(holes);
            //     perimeter = newPerimeter[0];
            //     holes = newPerimeter.Skip(1).Take(newPerimeter.Count - 1).ToArray();
            // }

            var  solid  = new Solid();
            Face fStart = null;

            if (bothSides)
            {
                var t = new Transform(direction.Negate() * (distance / 2), rotation);
                if (holes != null)
                {
                    fStart = solid.AddFace(perimeter, holes, transform: t, reverse: true);
                }
                else
                {
                    fStart = solid.AddFace(perimeter, transform: t, reverse: true);
                }
            }
            else
            {
                if (holes != null)
                {
                    fStart = solid.AddFace(perimeter, holes, reverse: true);
                }
                else
                {
                    fStart = solid.AddFace(perimeter, reverse: true);
                }
            }

            var fEndOuter = solid.SweepLoop(fStart.Outer, direction, distance);

            if (holes != null)
            {
                var fEndInner = new Loop[holes.Count];
                for (var i = 0; i < holes.Count; i++)
                {
                    fEndInner[i] = solid.SweepLoop(fStart.Inner[i], direction, distance);
                }
                solid.AddFace(fEndOuter, fEndInner);
            }
            else
            {
                solid.AddFace(fEndOuter);
            }

            return(solid);
        }
Пример #3
0
        /// <summary>
        /// Construct a solid by sweeping a face along a curve.
        /// </summary>
        /// <param name="perimeter">The perimeter of the face to sweep.</param>
        /// <param name="holes">The holes of the face to sweep.</param>
        /// <param name="curve">The curve along which to sweep.</param>
        /// <param name="startSetback">The setback distance of the sweep from the start of the curve.</param>
        /// <param name="endSetback">The setback distance of the sweep from the end of the curve.</param>
        /// <returns>A solid.</returns>
        public static Solid SweepFaceAlongCurve(Polygon perimeter,
                                                IList <Polygon> holes,
                                                ICurve curve,
                                                double startSetback = 0,
                                                double endSetback   = 0)
        {
            var solid = new Solid();

            var l = curve.Length();

            // The start and end setbacks can't be more than
            // the length of the beam together.
            if ((startSetback + endSetback) >= l)
            {
                startSetback = 0;
                endSetback   = 0;
            }

            // Calculate the setback parameter as a percentage
            // of the curve length. This will not work for curves
            // without non-uniform parameterization.
            var ssb = startSetback / l;
            var esb = endSetback / l;

            var transforms = curve.Frames(ssb, esb);

            if (curve is Polygon)
            {
                for (var i = 0; i < transforms.Length; i++)
                {
                    var next = i == transforms.Length - 1 ? transforms[0] : transforms[i + 1];
                    solid.SweepPolygonBetweenPlanes(perimeter, transforms[i], next);
                }
            }
            else if (curve is Bezier)
            {
                var startCap = solid.AddFace(perimeter, transform: transforms[0]);
                for (var i = 0; i < transforms.Length - 1; i++)
                {
                    var next = transforms[i + 1];
                    solid.SweepPolygonBetweenPlanes(perimeter, transforms[i], next);
                }
                var endCap = solid.AddFace(perimeter, transform: transforms[transforms.Length - 1], reverse: true);
            }
            else
            {
                // Add start cap.
                Face     cap = null;
                Edge[][] openEdges;

                if (holes != null)
                {
                    cap       = solid.AddFace(perimeter, holes, transform: transforms[0]);
                    openEdges = new Edge[1 + holes.Count][];
                }
                else
                {
                    cap       = solid.AddFace(perimeter, transform: transforms[0]);
                    openEdges = new Edge[1][];
                }

                // last outer edge
                var openEdge = cap.Outer.GetLinkedEdges();
                openEdge     = solid.SweepEdges(transforms, openEdge);
                openEdges[0] = openEdge;

                if (holes != null)
                {
                    for (var i = 0; i < cap.Inner.Length; i++)
                    {
                        openEdge = cap.Inner[i].GetLinkedEdges();

                        // last inner edge for one hole
                        openEdge         = solid.SweepEdges(transforms, openEdge);
                        openEdges[i + 1] = openEdge;
                    }
                }

                solid.Cap(openEdges, true);
            }

            return(solid);
        }