Esempio n. 1
0
 // We are going to try a few passes to add a curve to the CurveLoop, based on the fact that we can't always trust that the
 // orientation of the given curve loop is correct.  So we will:
 // 1. Try to add the curve, according to the orientation we believe is correct.
 // 2. Try to add the curve, reversing the orientation.
 // 3. Reverse the curve loop, and try steps 1-2 again.
 private void AddCurveToLoop(CurveLoop curveLoop, Curve curve, bool initialReverse, bool allowFlip)
 {
     try
     {
         AddCurveToLoopInternal(curveLoop, curve, initialReverse, false);
     }
     catch (Exception ex)
     {
         if (ex.Message.Contains("not contiguous"))
         {
             // One last attempt to solve the problem - flip the curve loop, try again.
             if (allowFlip)
             {
                 curveLoop.Flip();
                 AddCurveToLoop(curveLoop, curve, initialReverse, false);
             }
             else
             {
                 throw ex;
             }
         }
         else
         {
             throw ex;
         }
     }
 }
Esempio n. 2
0
        /// <summary>
        /// Reverses curve loop.
        /// </summary>
        /// <param name="curveloop">
        /// The curveloop.
        /// </param>
        /// <returns>
        /// The reversed curve loop.
        /// </returns>
        public static CurveLoop ReverseOrientation(CurveLoop curveloop)
        {
            CurveLoop copyOfCurveLoop = CurveLoop.CreateViaCopy(curveloop);

            copyOfCurveLoop.Flip();
            return(copyOfCurveLoop);
        }
Esempio n. 3
0
        /***************************************************/

        private static void AddLoop(this BRepBuilder brep, BRepBuilderGeometryId face, XYZ normal, ICurve curve, bool external)
        {
            CurveLoop cl = new CurveLoop();

            foreach (ICurve sp in curve.ISubParts())
            {
                foreach (Curve cc in sp.IToRevitCurves())
                {
                    cl.Append(cc);
                }
            }

            if (external != cl.IsCounterclockwise(normal))
            {
                cl.Flip();
            }

            BRepBuilderGeometryId loop = brep.AddLoop(face);

            foreach (Curve cc in cl)
            {
                BRepBuilderGeometryId edge = brep.AddEdge(BRepBuilderEdgeGeometry.Create(cc));
                brep.AddCoEdge(loop, edge, false);
            }

            brep.FinishLoop(loop);
        }
Esempio n. 4
0
        private CurveArray ConvertLoopToArray(CurveLoop loop)
        {
            CurveArray a = new CurveArray();

            if (loop.IsCounterclockwise(XYZ.BasisZ))
            {
                loop.Flip();
            }
            foreach (Curve c in loop)
            {
                a.Append(c);
            }

            return(a);
        }
Esempio n. 5
0
 // We are going to try a few passes to add a curve to the CurveLoop, based on the fact that we can't always trust that the
 // orientation of the given curve loop is correct.  So we will:
 // 1. Try to add the curve, according to the orientation we believe is correct.
 // 2. Try to add the curve, reversing the orientation.
 // 3. Reverse the curve loop, and try steps 1-2 again.
 private void AddCurveToLoop(CurveLoop curveLoop, Curve curve, bool initialReverse, bool allowFlip)
 {
     try
     {
         AddCurveToLoopInternal(curveLoop, curve, initialReverse, false);
     }
     catch (Exception ex)
     {
         if (ex.Message.Contains("not contiguous"))
         {
             // One last attempt to solve the problem - flip the curve loop, try again.
             if (allowFlip)
             {
                 curveLoop.Flip();
                 AddCurveToLoop(curveLoop, curve, initialReverse, false);
             }
             else
                 throw ex;
         }
         else
             throw ex;
     }
 }
Esempio n. 6
0
        /// <summary>
        /// Attempts to create a clipping, recess, or opening from a collection of faces.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="cuttingElement">The cutting element.  This will help determine whether to use a clipping or opening in boundary cases.</param>
        /// <param name="extrusionBasePlane">The plane of the extrusion base.</param>
        /// <param name="extrusionDirection">The extrusion direction.</param>
        /// <param name="faces">The collection of faces.</param>
        /// <param name="range">The valid range of the extrusion.</param>
        /// <param name="origBodyRepHnd">The original body representation.</param>
        /// <returns>The new body representation.  If the clipping completely clips the extrusion, this will be null.  Otherwise, this
        /// will be the clipped representation if a clipping was done, or the original representation if not.</returns>
        public static IFCAnyHandle ProcessFaceCollection(ExporterIFC exporterIFC, Element cuttingElement, Plane extrusionBasePlane,
                                                         XYZ extrusionDirection, ICollection <Face> faces, IFCRange range, IFCAnyHandle origBodyRepHnd)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(origBodyRepHnd))
            {
                return(null);
            }

            bool polygonalOnly = ExporterCacheManager.ExportOptionsCache.ExportAs2x2;

            IList <CurveLoop> outerCurveLoops      = new List <CurveLoop>();
            IList <Plane>     outerCurveLoopPlanes = new List <Plane>();
            IList <bool>      boundaryIsPolygonal  = new List <bool>();

            bool allPlanes    = true;
            UV   faceOriginUV = new UV(0, 0);

            foreach (Face face in faces)
            {
                FaceBoundaryType faceBoundaryType;
                CurveLoop        curveLoop = GetOuterFaceBoundary(face, null, polygonalOnly, out faceBoundaryType);
                outerCurveLoops.Add(curveLoop);
                boundaryIsPolygonal.Add(faceBoundaryType == FaceBoundaryType.Polygonal);

                if (face is PlanarFace)
                {
                    PlanarFace planarFace = face as PlanarFace;
                    XYZ        faceOrigin = planarFace.Origin;
                    XYZ        faceNormal = planarFace.ComputeNormal(faceOriginUV);

                    Plane plane = new Plane(faceNormal, faceOrigin);
                    outerCurveLoopPlanes.Add(plane);

                    if (!curveLoop.IsCounterclockwise(faceNormal))
                    {
                        curveLoop.Flip();
                    }
                }
                else
                {
                    outerCurveLoopPlanes.Add(null);
                    allPlanes = false;
                }
            }

            if (allPlanes)
            {
                int numFaces = faces.Count;

                // Special case: one face is a clip plane.
                if (numFaces == 1)
                {
                    return(ProcessClippingFace(exporterIFC, outerCurveLoops[0], outerCurveLoopPlanes[0], extrusionBasePlane,
                                               extrusionDirection, range, false, origBodyRepHnd));
                }

                KeyValuePair <bool, bool> clipsExtrusionEnds = CollectionClipsExtrusionEnds(outerCurveLoops, extrusionDirection, range);
                if (clipsExtrusionEnds.Key == true || clipsExtrusionEnds.Value == true)
                {
                    // Don't clip for a door, window or opening.
                    if (CreateOpeningForCategory(cuttingElement))
                    {
                        throw new Exception("Unhandled opening.");
                    }

                    ICollection <int> facesToSkip = new HashSet <int>();
                    bool clipStart = (clipsExtrusionEnds.Key == true);
                    bool clipBoth  = (clipsExtrusionEnds.Key == true && clipsExtrusionEnds.Value == true);
                    if (!clipBoth)
                    {
                        for (int ii = 0; ii < numFaces; ii++)
                        {
                            double slant = outerCurveLoopPlanes[ii].Normal.DotProduct(extrusionDirection);
                            if (!MathUtil.IsAlmostZero(slant))
                            {
                                if (clipStart && (slant > 0.0))
                                {
                                    throw new Exception("Unhandled clip plane direction.");
                                }
                                if (!clipStart && (slant < 0.0))
                                {
                                    throw new Exception("Unhandled clip plane direction.");
                                }
                            }
                            else
                            {
                                facesToSkip.Add(ii);
                            }
                        }
                    }
                    else
                    {
                        // If we are clipping both the start and end of the extrusion, we have to make sure all of the clipping
                        // planes have the same a non-negative dot product relative to one another.
                        int clipOrientation = 0;
                        for (int ii = 0; ii < numFaces; ii++)
                        {
                            double slant = outerCurveLoopPlanes[ii].Normal.DotProduct(extrusionDirection);
                            if (!MathUtil.IsAlmostZero(slant))
                            {
                                if (slant > 0.0)
                                {
                                    if (clipOrientation < 0)
                                    {
                                        throw new Exception("Unhandled clipping orientations.");
                                    }
                                    clipOrientation = 1;
                                }
                                else
                                {
                                    if (clipOrientation > 0)
                                    {
                                        throw new Exception("Unhandled clipping orientations.");
                                    }
                                    clipOrientation = -1;
                                }
                            }
                            else
                            {
                                facesToSkip.Add(ii);
                            }
                        }
                    }

                    IFCAnyHandle newBodyRepHnd = origBodyRepHnd;
                    for (int ii = 0; ii < numFaces; ii++)
                    {
                        if (facesToSkip.Contains(ii))
                        {
                            continue;
                        }

                        newBodyRepHnd = ProcessClippingFace(exporterIFC, outerCurveLoops[ii], outerCurveLoopPlanes[ii],
                                                            extrusionBasePlane, extrusionDirection, range, true, newBodyRepHnd);
                        if (newBodyRepHnd == null)
                        {
                            return(null);
                        }
                    }
                    return(newBodyRepHnd);
                }
            }

            bool unhandledCases = true;

            if (unhandledCases)
            {
                throw new Exception("Unhandled opening or clipping.");
            }

            // We will attempt to "sew" the faces, and see what we have left over.  Depending on what we have, we have an opening, recess, or clipping.
            IList <Edge> boundaryEdges = new List <Edge>();

            foreach (Face face in faces)
            {
                EdgeArrayArray faceBoundaries = face.EdgeLoops;
                // We only know how to deal with the outer loop; we'll throw if we have multiple boundaries.
                if (faceBoundaries.Size != 1)
                {
                    throw new Exception("Can't process faces with inner boundaries.");
                }

                EdgeArray faceBoundary = faceBoundaries.get_Item(0);
                foreach (Edge edge in faceBoundary)
                {
                    if (edge.get_Face(0) == null || edge.get_Face(1) == null)
                    {
                        boundaryEdges.Add(edge);
                    }
                }
            }

            return(origBodyRepHnd);
        }