예제 #1
0
        /// <summary>
        /// Check that all values in other are within epsilon of the values in this
        /// </summary>
        /// <param name="other"></param>
        /// <param name="epsilon"></param>
        /// <returns></returns>
        public bool EpsilonEquals(NurbsSurfaceKnotList other, double epsilon)
        {
            if (null == other)
            {
                throw new ArgumentNullException("other");
            }

            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            if (m_direction != other.m_direction)
            {
                return(false);
            }

            if (Count != other.Count)
            {
                return(false);
            }

            // check for equality of spans
            for (int i = 1; i < Count; ++i)
            {
                double myDelta    = this[i] - this[i - 1];
                double theirDelta = other[i] - other[i - 1];
                if (!RhinoMath.EpsilonEquals(myDelta, theirDelta, epsilon))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #2
0
 public bool EpsilonEquals(Quaternion other, double epsilon)
 {
     return(RhinoMath.EpsilonEquals(m_a, other.m_a, epsilon) &&
            RhinoMath.EpsilonEquals(m_b, other.m_b, epsilon) &&
            RhinoMath.EpsilonEquals(m_c, other.m_c, epsilon) &&
            RhinoMath.EpsilonEquals(m_d, other.m_d, epsilon));
 }
예제 #3
0
        /// <summary>
        /// Check that all values in other are within epsilon of the values in this
        /// </summary>
        /// <param name="other"></param>
        /// <param name="epsilon"></param>
        /// <returns></returns>
        public bool EpsilonEquals(NurbsCurvePointList other, double epsilon)
        {
            if (null == other)
            {
                throw new ArgumentNullException("other");
            }

            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            if (Count != other.Count)
            {
                return(false);
            }

            if (!RhinoMath.EpsilonEquals(ControlPolygonLength, other.ControlPolygonLength, epsilon))
            {
                return(false);
            }

            for (int i = 0; i < Count; ++i)
            {
                ControlPoint mine   = this[i];
                ControlPoint theirs = other[i];
                if (!mine.EpsilonEquals(theirs, epsilon))
                {
                    return(false);
                }
            }

            return(true);
        }
예제 #4
0
 public bool EpsilonEquals(Sphere other, double epsilon)
 {
     return(m_plane.EpsilonEquals(other.m_plane, epsilon) &&
            RhinoMath.EpsilonEquals(m_radius, other.m_radius, epsilon));
 }
예제 #5
0
 public bool EpsilonEquals(Arc other, double epsilon)
 {
     return(RhinoMath.EpsilonEquals(m_radius, other.m_radius, epsilon) &&
            m_plane.EpsilonEquals(other.m_plane, epsilon) &&
            m_angle.EpsilonEquals(other.m_angle, epsilon));
 }
예제 #6
0
 public bool EpsilonEquals(Cone other, double epsilon)
 {
     return(m_baseplane.EpsilonEquals(other.m_baseplane, epsilon) &&
            RhinoMath.EpsilonEquals(m_height, other.m_height, epsilon) &&
            RhinoMath.EpsilonEquals(m_radius, other.m_radius, epsilon));
 }
예제 #7
0
 public bool EpsilonEquals(Cylinder other, double epsilon)
 {
     return(m_basecircle.EpsilonEquals(other.m_basecircle, epsilon) &&
            RhinoMath.EpsilonEquals(m_height1, other.m_height1, epsilon) &&
            RhinoMath.EpsilonEquals(m_height2, other.m_height2, epsilon));
 }
예제 #8
0
        public static bool TryGetExtrusion(this Brep brep, out Extrusion extrusion)
        {
            if (brep.IsSurface)
            {
                return(brep.Faces[0].TryGetExtrusion(out extrusion));
            }

            extrusion = null;
            if (brep.Faces.Count < 3)
            {
                return(false);
            }

            // Requiere manifold breps
            if (brep.SolidOrientation == BrepSolidOrientation.None || brep.SolidOrientation == BrepSolidOrientation.Unknown)
            {
                return(false);
            }

            // If brep has more that 3 faces we should check if there are faces with interior loops
            if (brep.Faces.Count > 3 && brep.Faces.Where(face => face.Loops.Count != 1).Any())
            {
                return(false);
            }

            var candidateFaces = new List <int[]>();

            // Array with just planar faces sorted by its area to search for similar faces
            var planarFaces = brep.Faces.
                              Select(face => new PlanarBrepFace(face)).
                              Where(face => face.Plane.IsValid).
                              OrderByDescending(face => face.LoopArea).
                              ToArray();

            // A capped Extrusion converted to Brep has wall surfaces in face[0] to face[N-3], caps are face[N-2] and face[N-1]
            // I iterate in reverse order to be optimisitc, maybe brep comes from an Extrusion.ToBrep() call
            for (int f = planarFaces.Length - 1; f > 0; --f)
            {
                var planeF    = planarFaces[f].Plane;
                var loopF     = planarFaces[f].Loop;
                var centroidF = planarFaces[f].Centroid;

                // Check if they have same area.
                for (int g = f - 1; g >= 0 && RhinoMath.EpsilonEquals(planarFaces[f].LoopArea, planarFaces[g].LoopArea, RhinoMath.SqrtEpsilon); --g)
                {
                    // Planes should be parallel or anti-parallel
                    if (planeF.Normal.IsParallelTo(planarFaces[g].Plane.Normal, RhinoMath.DefaultAngleTolerance / 100.0) == 0)
                    {
                        continue;
                    }

                    // Here f, ang are perfect candidates to test adjacent faces for perpendicularity to them,
                    // but we may try to quick reject some candidates if it's obvious that doesn't match

                    // A "perfect" curve overlap match may be a test but is too much in this ocasion

                    // We expect same NURBS structure, so point count should match
                    if (loopF.Points.Count != planarFaces[g].Loop.Points.Count)
                    {
                        continue;
                    }

                    // Since we have computed the area the centroid comes for free.
                    // Centroids should also match
                    if (planeF.ClosestPoint(planarFaces[g].Centroid).DistanceToSquared(centroidF) > RhinoMath.SqrtEpsilon)
                    {
                        continue;
                    }

                    // Add result to candidates List reversing index order to keep extrusion creation direction
                    // Breps that come from a Extrusion have the Cap[0] before Cap[1]
                    candidateFaces.Add(new int[] { g, f });
                }
            }

            // No twin faces found
            if (candidateFaces.Count == 0)
            {
                return(false);
            }

            // Candidates are in 'LoopArea' order, we will find here smaller profiles sooner
            // This is good for beam like objects, bad for slab like objects.

            // On box-like Breps the result could be ambigous for the user so,
            // to give him some control on the result, we will prioritize first and last faces no matter their area.
            // First and Last are "special" because if somebody observe an extrusion-like Brep and sees
            // it as an extrusion he tends to categorize faces in one of the following schemas:
            // { Cap[0], Wall[0] .. Wall[N], Cap[1] }
            // { Cap[0], Cap[1], Wall[0] .. Wall[N] }
            // { Wall[0] .. Wall[N], Cap[0], Cap[1] }
            // So if he is using the join command to create a Brep from surfaces at the model,
            // it's natural to start or end the selection with one of the extrusion caps.
            // On horizontal extrusions, slab-like Breps, the user use to observe the model from above,
            // so probably he will end with the bottom cap.
            // Also Last face is a Cap in Breps that come from Extrusion
            // If caps and walls are interleaved, smallest pair of faces will be used as caps, producing beam-like extrusions.

            //  System.Linq.Enumerable.OrderBy performs a stable sort so only first and last face will be moved if found.
            foreach (var candidate in candidateFaces.OrderBy(pair => (planarFaces[pair[1]].Face.FaceIndex == brep.Faces.Count - 1) ? 0 : // Last,  in case it comes from Extrusion
                                                             (planarFaces[pair[0]].Face.FaceIndex == 0) ? 1 :                            // First, in case it comes from a JOIN command
                                                             int.MaxValue))                                                              // Others
            {
                var startFace = planarFaces[candidate[0]];
                var endFace   = planarFaces[candidate[1]];

                // If any face, ignorig twins candidates, does not degenrate
                // to a curve when projected to 'planeF', then brep is not an extrusion
                if
                (
                    brep.Faces.
                    Where(face => face.FaceIndex != startFace.Face.FaceIndex && face.FaceIndex != endFace.Face.FaceIndex).
                    Select(face => startFace.ProjectionDegenartesToCurve(face.UnderlyingSurface())).
                    Any(degenerateToCurve => degenerateToCurve == false)
                )
                {
                    return(false);
                }

                // We use the orginal OuterLoop as profile not the NURBS version of it
                // to keep the structure as much as possible
                var profile = startFace.Face.OuterLoop.To3dCurve();

                double height = startFace.Face.OrientationIsReversed ?
                                -startFace.Plane.DistanceTo(endFace.Plane.Origin) :
                                +startFace.Plane.DistanceTo(endFace.Plane.Origin);

                extrusion = Extrusion.Create(profile, height, true);
                return(true);
            }

            return(false);
        }
예제 #9
0
 public bool EpsilonEquals(Torus other, double epsilon)
 {
     return(m_majorCirclePlane.EpsilonEquals(other.m_majorCirclePlane, epsilon) &&
            RhinoMath.EpsilonEquals(m_majorRadius, other.m_majorRadius, epsilon) &&
            RhinoMath.EpsilonEquals(m_minorRadius, other.m_minorRadius, epsilon));
 }
예제 #10
0
 /// <summary>
 /// Check that all values in other are within epsilon of the values in this
 /// </summary>
 /// <param name="other"></param>
 /// <param name="epsilon"></param>
 /// <returns></returns>
 public bool EpsilonEquals(Ellipse other, double epsilon)
 {
     return(m_plane.EpsilonEquals(other.m_plane, epsilon) &&
            RhinoMath.EpsilonEquals(m_radius1, other.m_radius1, epsilon) &&
            RhinoMath.EpsilonEquals(m_radius2, other.m_radius2, epsilon));
 }
예제 #11
0
 /// <summary>
 /// Check that all values in other are withing epsilon of the values in this
 /// </summary>
 /// <param name="other"></param>
 /// <param name="epsilon"></param>
 /// <returns></returns>
 public bool EpsilonEquals(Vector3f other, float epsilon)
 {
     return(RhinoMath.EpsilonEquals(m_x, other.m_x, epsilon) &&
            RhinoMath.EpsilonEquals(m_y, other.m_y, epsilon) &&
            RhinoMath.EpsilonEquals(m_z, other.m_z, epsilon));
 }
예제 #12
0
 /// <summary>
 /// Check that all values in other are within epsilon of the values in this
 /// </summary>
 /// <param name="other"></param>
 /// <param name="epsilon"></param>
 /// <returns></returns>
 public bool EpsilonEquals(Point2f other, float epsilon)
 {
     return(RhinoMath.EpsilonEquals(m_x, other.m_x, epsilon) &&
            RhinoMath.EpsilonEquals(m_y, other.m_y, epsilon));
 }