private XYZ GetValidXVectorFromLoop(CurveLoop curveLoop, XYZ zVec, XYZ origin)
        {
            foreach (Curve curve in curveLoop)
            {
                IList<XYZ> pointsToCheck = new List<XYZ>();

                // If unbound, must be cyclic.
                if (!curve.IsBound)
                {
                    pointsToCheck.Add(curve.Evaluate(0, false));
                    pointsToCheck.Add(curve.Evaluate(Math.PI / 2.0, false));
                    pointsToCheck.Add(curve.Evaluate(Math.PI, false));
                }
                else
                {
                    pointsToCheck.Add(curve.Evaluate(0, true));
                    pointsToCheck.Add(curve.Evaluate(1.0, true));
                    if (curve.IsCyclic)
                        pointsToCheck.Add(curve.Evaluate(0.5, true));
                }

                foreach (XYZ pointToCheck in pointsToCheck)
                {
                    XYZ possibleVec = (pointToCheck - origin);
                    XYZ yVec = zVec.CrossProduct(possibleVec).Normalize();
                    if (yVec.IsZeroLength())
                        continue;
                    return yVec.CrossProduct(zVec);
                }
            }

            return null;
        }
        /// <summary>
        /// Determines if curve loop is counterclockwise.
        /// </summary>
        /// <param name="curveLoop">
        /// The curveLoop.
        /// </param>
        /// <param name="normal">
        /// The normal.
        /// </param>
        /// <returns>
        /// Returns true only if the loop is counterclockwise, false otherwise.
        /// </returns>
        public static bool IsIFCLoopCCW(CurveLoop curveLoop, XYZ normal)
        {
            if (curveLoop == null)
                throw new Exception("CurveLoop is null.");

            // If loop is not suitable for ccw evaluation an exception is thrown
            return curveLoop.IsCounterclockwise(normal);
        }
예제 #3
0
 protected override CurveLoop GenerateLoop()
 {
     CurveLoop curveLoop = new CurveLoop();
     foreach (IFCOrientedEdge edge in EdgeList) 
     {
         if (edge != null)
             curveLoop.Append(edge.GetGeometry());
     }
     return curveLoop;
 }
예제 #4
0
        public static Plane GetPlaneFromCurve(Curve c, bool planarOnly)
        {
            //find the plane of the curve and generate a sketch plane
            double period = c.IsBound ? 0.0 : (c.IsCyclic ? c.Period : 1.0);

            var p0 = c.IsBound ? c.Evaluate(0.0, true) : c.Evaluate(0.0, false);
            var p1 = c.IsBound ? c.Evaluate(0.5, true) : c.Evaluate(0.25 * period, false);
            var p2 = c.IsBound ? c.Evaluate(1.0, true) : c.Evaluate(0.5 * period, false);

            if (IsLineLike(c))
            {
                XYZ norm = null;

                //keep old plane computations
                if (System.Math.Abs(p0.Z - p2.Z) < Tolerance)
                {
                    norm = XYZ.BasisZ;
                }
                else
                {
                    var v1 = p1 - p0;
                    var v2 = p2 - p0;

                    var p3 = new XYZ(p2.X, p2.Y, p0.Z);
                    var v3 = p3 - p0;
                    norm = v1.CrossProduct(v3);
                    if (norm.IsZeroLength())
                    {
                        norm = v2.CrossProduct(XYZ.BasisY);
                    }
                    norm = norm.Normalize();
                }

                return new Plane(norm, p0);

            }

            var cLoop = new CurveLoop();
            cLoop.Append(c.Clone());
            if (cLoop.HasPlane())
            {
                return cLoop.GetPlane();
            }
            if (planarOnly)
                return null;

            // Get best fit plane using tesselation
            var points = c.Tessellate().Select(x => x.ToPoint(false));

            var bestFitPlane =
                Autodesk.DesignScript.Geometry.Plane.ByBestFitThroughPoints(points);

            return bestFitPlane.ToPlane(false);
        }
예제 #5
0
        /// <summary>
        /// Create a copy of a curve loop with a given transformation applied.
        /// </summary>
        /// <param name="origLoop">The original curve loop.</param>
        /// <param name="trf">The transform.</param>
        /// <returns>The transformed loop.</returns>
        public static CurveLoop CreateTransformed(CurveLoop origLoop, Transform trf)
        {
            if (origLoop == null)
                return null;

            CurveLoop newLoop = new CurveLoop();
            foreach (Curve curve in origLoop)
            {
                newLoop.Append(curve.CreateTransformed(trf));
            }
            return newLoop;
        }
        private static bool CurveLoopIsARectangle(CurveLoop curveLoop, out IList<int> cornerIndices)
        {
            cornerIndices = new List<int>(4);

            // looking for four orthogonal lines in one curve loop.
            int sz = curveLoop.Count();
            if (sz < 4)
                return false;

            IList<Line> lines = new List<Line>();
            foreach (Curve curve in curveLoop)
            {
                if (!(curve is Line))
                    return false;

                lines.Add(curve as Line);
            }

            sz = lines.Count;
            int numAngles = 0;

            // Must have 4 right angles found, and all other lines collinear -- if not, not a rectangle.
            for (int ii = 0; ii < sz; ii++)
            {
                double dot = lines[ii].Direction.DotProduct(lines[(ii + 1) % sz].Direction);
                if (MathUtil.IsAlmostZero(dot))
                {
                    if (numAngles > 3)
                        return false;
                    cornerIndices.Add(ii);
                    numAngles++;
                }
                else if (MathUtil.IsAlmostEqual(dot, 1.0))
                {
                    XYZ line0End1 = lines[ii].GetEndPoint(1);
                    XYZ line1End0 = lines[(ii + 1) % sz].GetEndPoint(0);
                    if (!line0End1.IsAlmostEqualTo(line1End0))
                        return false;
                }
                else
                    return false;
            }

            return (numAngles == 4);
        }
예제 #7
0
        /// <summary>
        /// A PolyCurve is not a curve, this is a special extension method to convert to a Revit CurveLoop
        /// </summary>
        /// <param name="pcrv"></param>
        /// <returns></returns>
        public static Autodesk.Revit.DB.CurveLoop ToRevitType(this Autodesk.DesignScript.Geometry.PolyCurve pcrv)
        {
            if (!pcrv.IsClosed)
            {
                throw new Exception("The input PolyCurve must be closed");
            }

            var cl = new CurveLoop();

            var crvs = pcrv.Curves();

            foreach (Autodesk.DesignScript.Geometry.Curve curve in crvs)
            {
                Autodesk.Revit.DB.Curve converted = curve.ToNurbsCurve().ToRevitType();
                cl.Append(converted);
            }

            return cl;

        }
예제 #8
0
        public static Autodesk.Revit.DB.CurveLoop ToRevitType(this Autodesk.DesignScript.Geometry.PolyCurve pcrv,
            bool performHostUnitConversion = true)
        {
            if (!pcrv.IsClosed)
            {
                throw new Exception("The input PolyCurve must be closed");
            }

            pcrv = performHostUnitConversion ? pcrv.InHostUnits() : pcrv;

            var cl = new CurveLoop();
            var crvs = pcrv.Curves();

            foreach (Autodesk.DesignScript.Geometry.Curve curve in crvs)
            {
                Autodesk.Revit.DB.Curve converted = curve.ToNurbsCurve().ToRevitType(false);
                cl.Append(converted);
            }

            return cl;
        }
예제 #9
0
        /// <summary>
        /// Create a curve representation of this IFCCompositeCurve from a curveloop
        /// </summary>
        /// <param name="curveLoop">The curveloop</param>
        /// <returns>A Revit curve that is made by appending every curve in the given curveloop, if possible</returns>
        private Curve ConvertCurveLoopIntoSingleCurve(CurveLoop curveLoop)
        {
            if (curveLoop == null)
            {
                return(null);
            }

            CurveLoopIterator curveIterator = curveLoop.GetCurveLoopIterator();
            Curve             firstCurve    = curveIterator.Current;
            Curve             returnCurve   = null;

            // We only connect the curves if they are Line, Arc or Ellipse
            if (!((firstCurve is Line) || (firstCurve is Arc) || (firstCurve is Ellipse)))
            {
                return(null);
            }

            XYZ firstStartPoint = firstCurve.GetEndPoint(0);

            Curve currentCurve = null;

            if (firstCurve is Line)
            {
                Line firstLine = firstCurve as Line;
                while (curveIterator.MoveNext())
                {
                    currentCurve = curveIterator.Current;
                    if (!(currentCurve is Line))
                    {
                        return(null);
                    }
                    Line currentLine = currentCurve as Line;

                    if (!(firstLine.Direction.IsAlmostEqualTo(currentLine.Direction)))
                    {
                        return(null);
                    }
                }
                returnCurve = Line.CreateBound(firstStartPoint, currentCurve.GetEndPoint(1));
            }
            else if (firstCurve is Arc)
            {
                Arc firstArc         = firstCurve as Arc;
                XYZ firstCurveNormal = firstArc.Normal;

                while (curveIterator.MoveNext())
                {
                    currentCurve = curveIterator.Current;
                    if (!(currentCurve is Arc))
                    {
                        return(null);
                    }

                    XYZ currentStartPoint = currentCurve.GetEndPoint(0);
                    XYZ currentEndPoint   = currentCurve.GetEndPoint(1);

                    Arc    currentArc    = currentCurve as Arc;
                    XYZ    currentCenter = currentArc.Center;
                    double currentRadius = currentArc.Radius;
                    XYZ    currentNormal = currentArc.Normal;

                    // We check if this circle is similar to the first circle by checking that they have the same center, same radius,
                    // and lie on the same plane
                    if (!(currentCenter.IsAlmostEqualTo(firstArc.Center) && MathUtil.IsAlmostEqual(currentRadius, firstArc.Radius)))
                    {
                        return(null);
                    }
                    if (!MathUtil.IsAlmostEqual(Math.Abs(currentNormal.DotProduct(firstCurveNormal)), 1))
                    {
                        return(null);
                    }
                }
                // If all of the curve segments are part of the same circle, then the returning curve will be a circle bounded
                // by the start point of the first curve and the end point of the last curve.
                XYZ lastPoint = currentCurve.GetEndPoint(1);
                if (lastPoint.IsAlmostEqualTo(firstStartPoint))
                {
                    firstCurve.MakeUnbound();
                }
                else
                {
                    double startParameter = firstArc.GetEndParameter(0);
                    double endParameter   = firstArc.Project(lastPoint).Parameter;

                    if (endParameter < startParameter)
                    {
                        endParameter += Math.PI * 2;
                    }

                    firstCurve.MakeBound(startParameter, endParameter);
                }
                returnCurve = firstCurve;
            }
            else if (firstCurve is Ellipse)
            {
                Ellipse firstEllipse     = firstCurve as Ellipse;
                double  radiusX          = firstEllipse.RadiusX;
                double  radiusY          = firstEllipse.RadiusY;
                XYZ     xDirection       = firstEllipse.XDirection;
                XYZ     yDirection       = firstEllipse.YDirection;
                XYZ     firstCurveNormal = firstEllipse.Normal;

                while (curveIterator.MoveNext())
                {
                    currentCurve = curveIterator.Current;
                    if (!(currentCurve is Ellipse))
                    {
                        return(null);
                    }

                    XYZ currentStartPoint = currentCurve.GetEndPoint(0);
                    XYZ currentEndPoint   = currentCurve.GetEndPoint(1);

                    Ellipse currentEllipse = currentCurve as Ellipse;
                    XYZ     currentCenter  = currentEllipse.Center;

                    double currentRadiusX    = currentEllipse.RadiusX;
                    double currentRadiusY    = currentEllipse.RadiusY;
                    XYZ    currentXDirection = currentEllipse.XDirection;
                    XYZ    currentYDirection = currentEllipse.YDirection;

                    XYZ currentNormal = currentEllipse.Normal;

                    if (!MathUtil.IsAlmostEqual(Math.Abs(currentNormal.DotProduct(firstCurveNormal)), 1))
                    {
                        return(null);
                    }

                    // We determine whether this ellipse is the same as the initial ellipse by checking if their centers and corresponding
                    // radiuses as well as radius directions are the same or permutations of each other.
                    if (!currentCenter.IsAlmostEqualTo(firstEllipse.Center))
                    {
                        return(null);
                    }

                    // Checks if the corresponding radius and radius direction are the same
                    if (MathUtil.IsAlmostEqual(radiusX, currentRadiusX))
                    {
                        if (!(MathUtil.IsAlmostEqual(radiusY, currentRadiusY) && currentXDirection.IsAlmostEqualTo(xDirection) && currentYDirection.IsAlmostEqualTo(yDirection)))
                        {
                            return(null);
                        }
                    }
                    // Checks if the corresponding radiuses and radius directions are permutations of each other
                    else if (MathUtil.IsAlmostEqual(radiusX, currentRadiusY))
                    {
                        if (!(MathUtil.IsAlmostEqual(radiusY, currentRadiusX) && currentXDirection.IsAlmostEqualTo(yDirection) && currentYDirection.IsAlmostEqualTo(xDirection)))
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        return(null);
                    }
                }

                // If all of the curve segments are part of the same ellipse then the returning curve will be the ellipse whose start point is the start
                // point of the first curve and the end point is the end point of the last curve
                XYZ lastPoint = currentCurve.GetEndPoint(1);
                if (lastPoint.IsAlmostEqualTo(firstStartPoint))
                {
                    firstCurve.MakeUnbound();
                }
                else
                {
                    double startParameter = firstEllipse.GetEndParameter(0);
                    double endParameter   = firstEllipse.Project(lastPoint).Parameter;

                    if (endParameter < startParameter)
                    {
                        endParameter += Math.PI * 2;
                    }
                    firstCurve.MakeBound(startParameter, endParameter);
                }
                returnCurve = firstCurve;
            }

            return(returnCurve);
        }
예제 #10
0
        /// <summary>
        /// Get the curve from the Axis representation of the given IfcProduct, transformed to the current local coordinate system.
        /// </summary>
        /// <param name="creator">The IfcProduct that may or may not contain a valid axis curve.</param>
        /// <param name="lcs">The local coordinate system.</param>
        /// <returns>The axis curve, if found, and valid.</returns>
        /// <remarks>In this case, we only allow bounded lines and arcs to be valid axis curves, as per IFC2x3 convention.
        /// The Curve may be contained as either a single Curve in the IFCCurve representation item, or it could be an
        /// open CurveLoop with one item.</remarks>
        private Curve GetAxisCurve(IFCProduct creator, Transform lcs)
        {
            // We need an axis curve to clip the extrusion profiles; if we can't get one, fail
            IFCProductRepresentation productRepresentation = creator.ProductRepresentation;

            if (productRepresentation == null)
            {
                return(null);
            }

            IList <IFCRepresentation> representations = productRepresentation.Representations;

            if (representations == null)
            {
                return(null);
            }

            foreach (IFCRepresentation representation in representations)
            {
                // Go through the list of representations for this product, to find the Axis representation.
                if (representation == null || representation.Identifier != IFCRepresentationIdentifier.Axis)
                {
                    continue;
                }

                IList <IFCRepresentationItem> items = representation.RepresentationItems;
                if (items == null)
                {
                    continue;
                }

                // Go through the list of representation items in the Axis representation, to look for the IfcCurve.
                foreach (IFCRepresentationItem item in items)
                {
                    if (item is IFCCurve)
                    {
                        // We will accept either a bounded Curve of type Line or Arc,
                        // or an open CurveLoop with one curve that satisfies the same condition.
                        IFCCurve ifcCurve  = item as IFCCurve;
                        Curve    axisCurve = ifcCurve.Curve;
                        if (axisCurve == null)
                        {
                            CurveLoop axisCurveLoop = ifcCurve.CurveLoop;
                            if (axisCurveLoop != null && axisCurveLoop.IsOpen() && axisCurveLoop.Count() == 1)
                            {
                                axisCurve = axisCurveLoop.First();
                                if (!(axisCurve is Line || axisCurve is Arc))
                                {
                                    axisCurve = null;
                                }
                            }
                        }

                        if (axisCurve != null)
                        {
                            return(axisCurve.CreateTransformed(lcs));
                        }
                    }
                }
            }

            return(null);
        }
 /// <summary>
 /// 梁柱连接
 /// </summary>
 /// <param name="beamList">梁的实例</param>
 /// <param name="colList">柱子的实例</param>
 /// <param name="doc">项目文档</param>
 private void JoinBeamAndColumns(ref List <FamilyInstance> beamList, List <FamilyInstance> colList, Document doc)
 {
     if (colList.Count != 0 && beamList.Count != 0)
     {
         List <XYZ>            colPosList = colList.ConvertAll(m => (m.Location as LocationPoint).Point);
         Level                 lev        = doc.GetElement(beamList[0].Host.Id) as Level;
         List <FamilyInstance> BeamNotJoinNowColListList = new List <FamilyInstance>();
         //需要改变定位线的梁、
         List <ElementId> beamElemChnageIds     = new List <ElementId>();
         List <Line>      beamLocationCurveList = new List <Line>();
         foreach (FamilyInstance col in colList)
         {
             XYZ       colPos         = (col.Location as LocationPoint).Point;
             XYZ       direction      = -XYZ.BasisZ;
             double    b              = col.Symbol.LookupParameter("b").AsDouble();
             double    h              = col.Symbol.LookupParameter("h").AsDouble();
             double    length         = b > h ? b : h;
             double    curveLoopWidth = length / 2 + 200 / 304.8;
             CurveLoop cuLoop         = new CurveLoop();
             double    x              = colPos.X;
             double    y              = colPos.Y;
             double    z              = lev.Elevation;
             //左上
             XYZ p1 = new XYZ(x - curveLoopWidth, y + curveLoopWidth, z);
             //左下
             XYZ p2 = p1 + new XYZ(0, -2 * curveLoopWidth, 0);
             //右下
             XYZ p3 = p2 + new XYZ(2 * curveLoopWidth, 0, 0);
             //右上
             XYZ   p4 = p3 + new XYZ(0, 2 * curveLoopWidth, 0);
             Curve c1 = Line.CreateBound(p1, p2);
             Curve c2 = Line.CreateBound(p2, p3);
             Curve c3 = Line.CreateBound(p3, p4);
             Curve c4 = Line.CreateBound(p4, p1);
             cuLoop.Append(c1);
             cuLoop.Append(c2);
             cuLoop.Append(c3);
             cuLoop.Append(c4);
             Solid intersectSolid = GeometryCreationUtilities.CreateExtrusionGeometry(new List <CurveLoop>()
             {
                 cuLoop
             }, direction, 200 / 304.8);
             ElementIntersectsSolidFilter ElemInsectSolidFilter = new ElementIntersectsSolidFilter(intersectSolid);
             IList <Element> beamNotJoinColList = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance))
                                                  .OfCategory(BuiltInCategory.OST_StructuralFraming).WherePasses(ElemInsectSolidFilter).ToElements().
                                                  Where(m => !JoinGeometryUtils.AreElementsJoined(doc, m, col)).ToList();
             //Transaction trans = new Transaction(doc, "创建内建模型");
             //trans.Start();
             //DirectShapeType drt = DirectShapeType.Create(doc, "实体", new ElementId(BuiltInCategory.OST_Parts));
             //DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_Parts), Guid.NewGuid().ToString(), Guid.NewGuid().ToString());
             //ds.SetShape(new List<GeometryObject>() { intersectSolid });
             //ds.SetTypeId(drt.Id);
             //trans.Commit();
             //TaskDialog.Show("biao", "uu");
             foreach (Element e in beamNotJoinColList)
             {
                 //判断是否发生了变化
                 bool pd = true;
                 Line l  = (e.Location as LocationCurve).Curve is Line ? (e.Location as LocationCurve).Curve as Line : null;
                 if (l == null)
                 {
                     continue;
                 }
                 XYZ lp1  = l.GetEndPoint(0);
                 XYZ lp2  = l.GetEndPoint(1);
                 XYZ dirt = (lp1 - lp2) / lp1.DistanceTo(lp2);
                 //当柱端点与梁端点相距不超过某个值是默认让其相交
                 XYZ pi = new XYZ(x, y, z);
                 if (lp1.DistanceTo(pi) < curveLoopWidth)
                 {
                     if (dirt.IsAlmostEqualTo(new XYZ(0, 1, 0)) || dirt.IsAlmostEqualTo(new XYZ(0, -1, 0)))
                     {
                         lp1 = new XYZ(lp1.X, pi.Y, lev.Elevation);
                     }
                     else if (dirt.IsAlmostEqualTo(new XYZ(-1, 0, 0)) || dirt.IsAlmostEqualTo(new XYZ(1, 0, 0)))
                     {
                         lp1 = new XYZ(pi.X, lp1.Y, lev.Elevation);
                     }
                     else
                     {
                         continue;
                     }
                 }
                 else if (lp2.DistanceTo(pi) < curveLoopWidth)
                 {
                     if (dirt.IsAlmostEqualTo(new XYZ(0, 1, 0)) || dirt.IsAlmostEqualTo(new XYZ(0, -1, 0)))
                     {
                         lp2 = new XYZ(lp2.X, pi.Y, lev.Elevation);
                     }
                     else if (dirt.IsAlmostEqualTo(new XYZ(-1, 0, 0)) || dirt.IsAlmostEqualTo(new XYZ(1, 0, 0)))
                     {
                         lp2 = new XYZ(pi.X, lp2.Y, lev.Elevation);
                     }
                     else
                     {
                         continue;
                     }
                 }
                 else
                 {
                     pd = false;
                 }
                 if (pd == true)
                 {
                     if (beamElemChnageIds.Count() == 0 || beamElemChnageIds.Where(m => m == e.Id).Count() == 0)
                     {
                         beamElemChnageIds.Add(e.Id);
                         beamLocationCurveList.Add(Line.CreateBound(lp1, lp2));
                     }
                     else
                     {
                         int  index     = beamElemChnageIds.IndexOf(e.Id);
                         Line indexLine = beamLocationCurveList.ElementAt(index);
                         XYZ  pone      = indexLine.GetEndPoint(0);
                         XYZ  ptwo      = indexLine.GetEndPoint(1);
                         //变化的线
                         Line linelast1 = Line.CreateBound(pone, lp2);
                         Line linelast2 = Line.CreateBound(lp1, ptwo);
                         beamLocationCurveList[index] = linelast1.Length > linelast2.Length ? linelast1 : linelast2;
                     }
                 }
             }
         }
         //创建新的梁实例
         using (Transaction transChange = new Transaction(doc))
         {
             transChange.Start("join");
             foreach (ElementId beamId in beamElemChnageIds)
             {
                 int     index = beamElemChnageIds.IndexOf(beamId);
                 Element beam  = doc.GetElement(beamId);
                 (beam.Location as LocationCurve).Curve = beamLocationCurveList[index];
                 TaskDialog.Show("kaishi", "sdduas");
             }
             transChange.Commit();
         }
         using (Transaction trans = new Transaction(doc, "调整顺序"))
         {
             trans.Start();
             //梁柱剪切关系
             foreach (FamilyInstance col in colList)
             {
                 foreach (FamilyInstance beam in beamList)
                 {
                     if (JoinGeometryUtils.AreElementsJoined(doc, beam, col) == true)
                     {
                         if (JoinGeometryUtils.IsCuttingElementInJoin(doc, beam, col))
                         {
                             JoinGeometryUtils.SwitchJoinOrder(doc, col, beam);
                         }
                     }
                 }
             }
             trans.Commit();
         }
     }
 }
예제 #12
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;
 }
예제 #13
0
        private static IList<UV> TransformAndProjectCurveLoopToPlane(ExporterIFC exporterIFC, CurveLoop loop, Plane projScaledPlane)
        {
            IList<UV> uvs = new List<UV>();

            XYZ projDir = projScaledPlane.Normal;
            foreach (Curve curve in loop)
            {
                XYZ point = curve.get_EndPoint(0);
                XYZ scaledPoint = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, point);

                UV scaledUV = ProjectPointToPlane(projScaledPlane, projDir, scaledPoint);
                uvs.Add(scaledUV);
            }
            return uvs;
        }
예제 #14
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument    uidoc = uiapp.ActiveUIDocument;
            Document      doc   = uidoc.Document;


            Reference r = uidoc.Selection.PickObject(ObjectType.Element, "Select Element");

            Options geometryOptions = new Options();

            geometryOptions.ComputeReferences = false;

            GeometryElement geomElem = doc.GetElement(r).get_Geometry(geometryOptions);

            List <NurbSpline> cadSplines = new List <NurbSpline>();

            IList <XYZ>   controlPoints = new List <XYZ>();
            List <double> weights       = new List <double>();
            List <double> knots         = new List <double>();

            if (null != geomElem)
            {
                foreach (var o in geomElem)
                {
                    GeometryInstance gi = o as GeometryInstance;
                    GeometryElement  instanceGeometryElement = gi.GetInstanceGeometry();

                    foreach (GeometryObject instanceObj in instanceGeometryElement)
                    {
                        if (instanceObj.GetType().ToString().Contains("NurbSpline"))
                        {
                            //TaskDialog.Show("r", instanceObj.GetType().ToString());
                            NurbSpline nurb = instanceObj as NurbSpline;
                            cadSplines.Add(nurb);
                            controlPoints = nurb.CtrlPoints;
                            //weights = nurb.Weights;
                            weights = nurb.Weights.Cast <double>().ToList();
                            //knots = nurb.Knots;
                            knots = nurb.Knots.Cast <double>().ToList();
                        }
                        break;
                    }
                }
            }

            double scale = 0.3048;

            #region Test
            //List<XYZ> controlPoints = new List<XYZ>();
            //controlPoints.Add(new XYZ(0 / scale, 0 / scale, 0 / scale));
            //controlPoints.Add(new XYZ(5 / scale, 5 / scale, 2 / scale));
            //controlPoints.Add(new XYZ(10 / scale, 10 / scale, 5 / scale));
            //controlPoints.Add(new XYZ(15 / scale, 10 / scale, 5 / scale));
            //controlPoints.Add(new XYZ(20 / scale, 5 / scale, 4 / scale));
            //controlPoints.Add(new XYZ(25 / scale, 5 / scale, 3 / scale));

            //List<double> weights = new List<double>();
            //weights.Add(1.0);
            //weights.Add(1.0);
            //weights.Add(1.0);
            //weights.Add(1.0);
            //weights.Add(1.0);
            //weights.Add(1.0);

            //List<double> knots = new List<double>();
            //knots.Add(0); //1revit
            //knots.Add(0); //2
            //knots.Add(0); //3
            //knots.Add(0); //4
            //knots.Add(10.76); //5
            //knots.Add(21.51); //6
            //knots.Add(32.27); //7
            //knots.Add(32.27);
            //knots.Add(32.27); //9
            //knots.Add(32.27);//revit
            #endregion

            HermiteSpline hermspline = HermiteSpline.Create(controlPoints, false);

            //Curve nurbSpline = NurbSpline.Create(hermspline);
            Curve nurbSpline = NurbSpline.CreateCurve(3, knots, controlPoints, weights);

            //XYZ startPoint = nurbSpline.GetEndPoint(0);

            Transform nurbsTr = nurbSpline.ComputeDerivatives(0, true);

            XYZ startPoint = nurbsTr.Origin;
            //PrintPoint("a", nurbsTr.Origin);

            #region Test Plane
            //Plane geomPlane = Autodesk.Revit.DB.Plane.CreateByOriginAndBasis(nurbsTr.Origin, nurbsTr.BasisY.Normalize(), nurbsTr.BasisZ.Normalize());
            //Plane geomPlane = Autodesk.Revit.DB.Plane.CreateByOriginAndBasis(nurbSpline.GetEndPoint(0), nurbsTr.BasisY.Normalize(), nurbsTr.BasisZ.Normalize());
            //Frame f = new Frame(nurbSpline.GetEndPoint(0), nurbsTr.BasisY.Normalize(), nurbsTr.BasisZ.Normalize(), nurbsTr.BasisX.Normalize());
            //Plane geomPlane = Autodesk.Revit.DB.Plane.CreateByThreePoints(XYZ.Zero, XYZ.BasisX, XYZ.BasisZ);
            //Plane geomPlane = Plane.CreateByNormalAndOrigin(nurbsTr.BasisX.Normalize(), nurbSpline.GetEndPoint(1)); funziona
            //Plane geomPlane = Plane.CreateByThreePoints(startPoint, startPoint + nurbsTr.BasisX.Normalize(), startPoint + XYZ.BasisZ);
            #endregion
            //XYZ curveDir = controlPoints[1] - controlPoints[0];
            XYZ   curveDir  = nurbsTr.BasisX;
            XYZ   perpDir   = curveDir.CrossProduct(startPoint + XYZ.BasisZ).Normalize();
            Plane perpPlane = Plane.CreateByNormalAndOrigin(curveDir, startPoint);
            //Plane vertPlane = Plane.CreateByThreePoints(startPoint, perpPlane.XVec, XYZ.BasisZ);
            Plane vertPlane = perpPlane;

            //PrintPoint("per", perpDir);

            List <PtCoord> pointsCoordinates = new List <PtCoord>();

            using (var form = new FormAddActiveView("Enter coordinates in clockwise order"))
            {
                form.ShowDialog();

                //if the user hits cancel just drop out of macro
                if (form.DialogResult == System.Windows.Forms.DialogResult.Cancel)
                {
                    return(Result.Cancelled);
                }

                string[] inputs = form.TextString.Split(';');

                foreach (string coord in inputs)
                {
                    string[] xy = coord.Split(',');
                    pointsCoordinates.Add(new PtCoord(Double.Parse(xy[0]) / (scale * 1000), Double.Parse(xy[1]) / (scale * 1000)));
                }
            }

//			List<PtCoord> pointsCoordinates = new List<PtCoord>(){new PtCoord(5,0), new PtCoord(2,2), new PtCoord(-14,0), new PtCoord(2,-2)};

            List <XYZ> pts = VertexPoints(nurbsTr.Origin, pointsCoordinates, vertPlane);

            XYZ pt1 = nurbsTr.Origin;
            XYZ pt2 = pt1 + vertPlane.XVec * 5;
            XYZ pt3 = pt2 + vertPlane.YVec * 2 + vertPlane.XVec * 2;
            XYZ pt4 = pt3 - vertPlane.XVec * 12;
            XYZ pt5 = pt4 - vertPlane.YVec * 2 + vertPlane.XVec * 2;



            Line l1 = Line.CreateBound(pt1, pt2);
            Line l2 = Line.CreateBound(pt2, pt3);
            Line l3 = Line.CreateBound(pt3, pt4);
            Line l4 = Line.CreateBound(pt4, pt5);
            Line l5 = Line.CreateBound(pt5, pt1);
            //
            //			var profileLoop = CurveLoop.Create(new List<Curve>{l1, l2, l3, l4, l5});

            var profileLoop = LoopPoints(pts);

            //double rotAngle = -2.543 * Math.PI / 180;
            double rotAngle  = -15 * Math.PI / 180;
            var    transform = Transform.CreateRotationAtPoint(nurbsTr.BasisX, rotAngle, nurbsTr.Origin);

            profileLoop.Transform(transform);

            var loops = new List <CurveLoop> {
                profileLoop
            };

            var path = CurveLoop.Create(new List <Curve> {
                nurbSpline
            });

            WireframeBuilder builder = new WireframeBuilder();

            builder.AddCurve(nurbSpline);


            //Solid solid = GeometryCreationUtilities.CreateSweptGeometry(path,0,nurbSpline.GetEndParameter(0),loops);
            Solid solid = GeometryCreationUtilities.CreateFixedReferenceSweptGeometry(path, 0, nurbSpline.GetEndParameter(0), loops, XYZ.BasisZ);


            using (Transaction t = new Transaction(doc, "create spline"))
            {
                t.Start();

                ElementId categoryId = new ElementId(BuiltInCategory.OST_Floors);

                DirectShape ds = DirectShape.CreateElement(doc, categoryId);

                ds.SetShape(builder);

                ds.Name = "RhinoSpline";

                SketchPlane sp = SketchPlane.Create(doc, vertPlane);
                uidoc.ActiveView.SketchPlane = sp;

                //uidoc.ActiveView.ShowActiveWorkPlane();

                ModelLine line1 = doc.Create.NewModelCurve(l1, sp) as ModelLine;
                ModelLine line2 = doc.Create.NewModelCurve(l2, sp) as ModelLine;
                ModelLine line3 = doc.Create.NewModelCurve(l3, sp) as ModelLine;
                ModelLine line4 = doc.Create.NewModelCurve(l4, sp) as ModelLine;
                ModelLine line5 = doc.Create.NewModelCurve(l5, sp) as ModelLine;

                List <GeometryObject> gs = new List <GeometryObject>();
                gs.Add(solid);

                //DirectShape directShape = DirectShape.CreateElement(doc, categoryId);
                ds.AppendShape(gs);

                t.Commit();
            }

            return(Result.Succeeded);
        }
예제 #15
0
        /// <summary>
        /// Create geometry for an IfcHalfSpaceSolid.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>A list containing one geometry for the IfcHalfSpaceSolid.</returns>
        protected virtual IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            IFCPlane ifcPlane = BaseSurface as IFCPlane;
            Plane    plane    = ifcPlane.Plane;
            XYZ      origin   = plane.Origin;
            XYZ      xVec     = plane.XVec;
            XYZ      yVec     = plane.YVec;

            // Set some huge boundaries for now.
            const double largeCoordinateValue = 100000;

            XYZ[] corners = new XYZ[4] {
                lcs.OfPoint((xVec * -largeCoordinateValue) + (yVec * -largeCoordinateValue) + origin),
                lcs.OfPoint((xVec * largeCoordinateValue) + (yVec * -largeCoordinateValue) + origin),
                lcs.OfPoint((xVec * largeCoordinateValue) + (yVec * largeCoordinateValue) + origin),
                lcs.OfPoint((xVec * -largeCoordinateValue) + (yVec * largeCoordinateValue) + origin)
            };

            IList <CurveLoop> loops = new List <CurveLoop>();
            CurveLoop         loop  = new CurveLoop();

            for (int ii = 0; ii < 4; ii++)
            {
                if (AgreementFlag)
                {
                    loop.Append(Line.CreateBound(corners[(5 - ii) % 4], corners[(4 - ii) % 4]));
                }
                else
                {
                    loop.Append(Line.CreateBound(corners[ii], corners[(ii + 1) % 4]));
                }
            }
            loops.Add(loop);

            XYZ          normal       = lcs.OfVector(AgreementFlag ? -plane.Normal : plane.Normal);
            SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            Solid        baseSolid    = GeometryCreationUtilities.CreateExtrusionGeometry(loops, normal, largeCoordinateValue, solidOptions);

            if (BaseBoundingCurve != null)
            {
                CurveLoop polygonalBoundary = BaseBoundingCurve.CurveLoop;

                Transform totalTransform = lcs.Multiply(BaseBoundingCurveTransform);

                // Make sure this bounding polygon extends below base of half-space soild.
                Transform moveBaseTransform = Transform.Identity;
                moveBaseTransform.Origin = new XYZ(0, 0, -largeCoordinateValue);
                totalTransform           = totalTransform.Multiply(moveBaseTransform);

                CurveLoop         transformedPolygonalBoundary = IFCGeometryUtil.CreateTransformed(polygonalBoundary, totalTransform);
                IList <CurveLoop> boundingLoops = new List <CurveLoop>();
                boundingLoops.Add(transformedPolygonalBoundary);

                Solid boundingSolid = GeometryCreationUtilities.CreateExtrusionGeometry(boundingLoops, totalTransform.BasisZ, 2.0 * largeCoordinateValue,
                                                                                        solidOptions);
                baseSolid = IFCGeometryUtil.ExecuteSafeBooleanOperation(Id, BaseBoundingCurve.Id, baseSolid, boundingSolid, BooleanOperationsType.Intersect);
            }

            IList <GeometryObject> returnList = new List <GeometryObject>();

            returnList.Add(baseSolid);
            return(returnList);
        }
예제 #16
0
        /// <summary>
        /// Trims the CurveLoop contained in an IFCCurve by the start and optional end parameter values.
        /// </summary>
        /// <param name="id">The id of the IFC entity containing the directrix, for messaging purposes.</param>
        /// <param name="ifcCurve">The IFCCurve entity containing the CurveLoop to be trimmed.</param>
        /// <param name="startVal">The starting trim parameter.</param>
        /// <param name="origEndVal">The optional end trim parameter.  If not supplied, assume no end trim.</param>
        /// <returns>The original curve loop, if no trimming has been done, otherwise a trimmed copy.</returns>
        public static CurveLoop TrimCurveLoop(int id, IFCCurve ifcCurve, double startVal, double?origEndVal)
        {
            CurveLoop origCurveLoop = ifcCurve.GetCurveLoop();

            if (origCurveLoop == null)
            {
                return(null);
            }

            // Trivial case: no trimming.
            if (!origEndVal.HasValue && MathUtil.IsAlmostZero(startVal))
            {
                return(origCurveLoop);
            }

            IList <double> curveLengths = new List <double>();
            IList <Curve>  loopCurves   = new List <Curve>();

            double totalParamLength = 0.0;

            bool allLines = true;

            foreach (Curve curve in origCurveLoop)
            {
                if (!(curve is Line))
                {
                    allLines = false;
                }

                double curveLength = curve.GetEndParameter(1) - curve.GetEndParameter(0);
                double currLength  = ScaleCurveLengthForSweptSolid(curve, curveLength);
                loopCurves.Add(curve);
                curveLengths.Add(currLength);
                totalParamLength += currLength;
            }

            double endVal = origEndVal.HasValue ? origEndVal.Value : totalParamLength;

            // This check allows for some leniency in the setting of startVal and endVal; we assume that if the parameter range
            // is equal, that an offset value is OK.
            double curveParamLength = endVal - startVal;

            if (MathUtil.IsAlmostEqual(curveParamLength, totalParamLength))
            {
                return(origCurveLoop);
            }

            // Error in some Tekla files - lines are parameterized by length, instead of 1.0 (as is correct).
            // Warn and ignore the parameter length.  This must come after the MathUtil.IsAlmostEqual(curveParamLength, totalParamLength)
            // check above, since we don't want to warn if curveParamLength == totalParamLength.
            if (!CheckIfTrimParametersAreValidForSomeInvalidities(id, ifcCurve, curveParamLength))
            {
                return(origCurveLoop);
            }

            // Special cases:
            // if startval = 0 and endval = 1 and we have a polyline, then this likely means that the importing application
            // incorrectly set the extents to be the "whole" curve, when really this is just a portion of the curves
            // (the parametrization is described above).
            // As such, if the totalParamLength is not 1 but startVal = 0 and endVal = 1, we will warn but not trim.
            // This is not a hypothetical case: it occurs in several AllPlan 2017 files at least.
            if (allLines)
            {
                if ((!MathUtil.IsAlmostEqual(totalParamLength, 1.0)) && (MathUtil.IsAlmostZero(startVal) && MathUtil.IsAlmostEqual(endVal, 1.0)))
                {
                    Importer.TheLog.LogWarning(id, "The Start Parameter for the trimming of this curve was set to 0, and the End Parameter was set to 1.  " +
                                               "Most likely, this is an error in the sending application, and the trim extents are being ignored.  " +
                                               "If this trim was intended, please contact Autodesk.", true);
                    return(origCurveLoop);
                }
            }

            int    numCurves       = loopCurves.Count;
            double currentPosition = 0.0;
            int    currCurve       = 0;

            IList <Curve> newLoopCurves = new List <Curve>();

            if (startVal > MathUtil.Eps())
            {
                for (; currCurve < numCurves; currCurve++)
                {
                    if (currentPosition + curveLengths[currCurve] < startVal + MathUtil.Eps())
                    {
                        currentPosition += curveLengths[currCurve];
                        continue;
                    }

                    Curve newCurve = loopCurves[currCurve].Clone();
                    if (!MathUtil.IsAlmostEqual(currentPosition, startVal))
                    {
                        newCurve.MakeBound(UnscaleSweptSolidCurveParam(loopCurves[currCurve], startVal - currentPosition), newCurve.GetEndParameter(1));
                    }

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

            if (endVal < totalParamLength - MathUtil.Eps())
            {
                for (; currCurve < numCurves; currCurve++)
                {
                    if (currentPosition + curveLengths[currCurve] < endVal - MathUtil.Eps())
                    {
                        currentPosition += curveLengths[currCurve];
                        newLoopCurves.Add(loopCurves[currCurve]);
                        continue;
                    }

                    Curve newCurve = loopCurves[currCurve].Clone();
                    if (!MathUtil.IsAlmostEqual(currentPosition + curveLengths[currCurve], endVal))
                    {
                        newCurve.MakeBound(newCurve.GetEndParameter(0), UnscaleSweptSolidCurveParam(loopCurves[currCurve], endVal - currentPosition));
                    }

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

            CurveLoop trimmedCurveLoop = new CurveLoop();

            foreach (Curve curve in newLoopCurves)
            {
                trimmedCurveLoop.Append(curve);
            }
            return(trimmedCurveLoop);
        }
예제 #17
0
        private static bool GetCalloutCornerPoints(Document doc, ElementId calloutId, out XYZ firstPoint, out XYZ secondPoint)
        {
            bool result = false;

            firstPoint  = new XYZ(0, 0, 0);
            secondPoint = new XYZ(0, 0, 0);
            try
            {
                double minX = double.MaxValue;
                double minY = double.MaxValue;
                double minZ = double.MaxValue;
                double maxX = double.MinValue;
                double maxY = double.MinValue;
                double maxZ = double.MinValue;

                ViewCropRegionShapeManager cropRegion = View.GetCropRegionShapeManagerForReferenceCallout(doc, calloutId);
#if RELEASE2016 || RELEASE2017
                IList <CurveLoop> curveLoops = cropRegion.GetCropShape();
                foreach (CurveLoop cLoop in curveLoops)
                {
                    foreach (Curve curve in cLoop)
                    {
                        XYZ point = curve.GetEndPoint(0);
                        if (point.X < minX)
                        {
                            minX = point.X;
                        }
                        if (point.Y < minY)
                        {
                            minY = point.Y;
                        }
                        if (point.Z < minZ)
                        {
                            minZ = point.Z;
                        }
                        if (point.X > maxX)
                        {
                            maxX = point.X;
                        }
                        if (point.Y > maxY)
                        {
                            maxY = point.Y;
                        }
                        if (point.Z > maxZ)
                        {
                            maxZ = point.Z;
                        }
                    }
                }

                if (curveLoops.Count() > 0)
                {
                    firstPoint  = new XYZ(minX, minY, minZ);
                    secondPoint = new XYZ(maxX, maxY, maxZ);
                    result      = true;
                }
#else
                CurveLoop curveLoop = cropRegion.GetCropRegionShape();
                foreach (Curve curve in curveLoop)
                {
                    XYZ point = curve.GetEndPoint(0);
                    if (point.X < minX)
                    {
                        minX = point.X;
                    }
                    if (point.Y < minY)
                    {
                        minY = point.Y;
                    }
                    if (point.Z < minZ)
                    {
                        minZ = point.Z;
                    }
                    if (point.X > maxX)
                    {
                        maxX = point.X;
                    }
                    if (point.Y > maxY)
                    {
                        maxY = point.Y;
                    }
                    if (point.Z > maxZ)
                    {
                        maxZ = point.Z;
                    }
                }

                if (curveLoop.Count() > 0)
                {
                    firstPoint  = new XYZ(minX, minY, minZ);
                    secondPoint = new XYZ(maxX, maxY, maxZ);
                    result      = true;
                }
#endif
            }
            catch (Exception ex)
            {
                errorMessage.AppendLine("Failed to get corner points of callout.\n" + ex.Message);
                //MessageBox.Show("Failed to get corner points of callout\n" + ex.Message, "Get Corner Points of Callout", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
            return(result);
        }
예제 #18
0
        /// <summary>
        /// Create a copy of a curve loop with a given non-transformal transformation applied.
        /// </summary>
        /// <param name="origLoop">The original curve loop.</param>
        /// <param name="id">The id of the originating entity, for error reporting.</param>
        /// <param name="unscaledTrf">The unscaled (conformal) transform, used if we don't know how to process the curve loop.</param>
        /// <param name="scaledTrf">The scaled transform.</param>
        /// <returns>The transformed loop.</returns>
        /// <remarks>Revit API only allows for conformal transformations.  Here, we support
        /// enough data types for non-conformal cases.  In cases where we can't process
        /// a curve in the loop, we will use the conformal parameter and log an error.</remarks>
        public static CurveLoop CreateTransformed(CurveLoop origLoop, int id, Transform unscaledTrf, Transform scaledTrf)
        {
            if (origLoop == null)
            {
                return(null);
            }

            if (scaledTrf.IsConformal)
            {
                return(CreateTransformedFromConformalTransform(origLoop, scaledTrf));
            }

            CurveLoop newLoop = new CurveLoop();

            foreach (Curve curve in origLoop)
            {
                Curve newCurve = null;
                try
                {
                    // Cover only Line, Arc, and Ellipse for now.  These are the most common cases.  Warn if it isn't one of these, or if the
                    if (curve is Line)
                    {
                        Line line         = curve as Line;
                        XYZ  newEndPoint0 = scaledTrf.OfPoint(line.GetEndPoint(0));
                        XYZ  newEndPoint1 = scaledTrf.OfPoint(line.GetEndPoint(1));
                        newCurve = Line.CreateBound(newEndPoint0, newEndPoint1);
                    }
                    else if (curve is Arc || curve is Ellipse)
                    {
                        double startParam = curve.GetEndParameter(0);
                        double endParam   = curve.GetEndParameter(1);

                        XYZ    center  = null;
                        XYZ    xAxis   = null;
                        XYZ    yAxis   = null;
                        double radiusX = 0.0;
                        double radiusY = 0.0;

                        if (curve is Arc)
                        {
                            Arc arc = curve as Arc;
                            center = arc.Center;
                            xAxis  = arc.XDirection;
                            yAxis  = arc.YDirection;

                            radiusX = radiusY = arc.Radius;
                        }
                        else if (curve is Ellipse)
                        {
                            Ellipse ellipse = curve as Ellipse;

                            center = ellipse.Center;
                            xAxis  = ellipse.XDirection;
                            yAxis  = ellipse.YDirection;

                            radiusX = ellipse.RadiusX;
                            radiusY = ellipse.RadiusY;
                        }

                        XYZ radiusXDir       = new XYZ(radiusX, 0, 0);
                        XYZ radiusYDir       = new XYZ(0, radiusY, 0);
                        XYZ scaledRadiusXDir = scaledTrf.OfVector(radiusXDir);
                        XYZ scaledRadiusYDir = scaledTrf.OfVector(radiusYDir);

                        double scaledRadiusX = scaledRadiusXDir.GetLength();
                        double scaledRadiusY = scaledRadiusYDir.GetLength();

                        XYZ scaledCenter = scaledTrf.OfPoint(center);
                        XYZ scaledXAxis  = scaledTrf.OfVector(xAxis).Normalize();
                        XYZ scaledYAxis  = scaledTrf.OfVector(yAxis).Normalize();
                        newCurve = CreateArcOrEllipse(scaledCenter, scaledRadiusX, scaledRadiusY, scaledXAxis, scaledYAxis, startParam, endParam);
                    }
                }
                catch (Exception)
                {
                    newCurve = null;
                }

                if (newCurve == null)
                {
                    Importer.TheLog.LogError(id, "Couldn't apply a non-uniform transform to this curve loop.  The resulting geometry may be the wrong size.", false);
                    return(CreateTransformedFromConformalTransform(origLoop, unscaledTrf));
                }
                else
                {
                    newLoop.Append(newCurve);
                }
            }
            return(newLoop);
        }
예제 #19
0
 private static Polygon ToPolygon(this CurveLoop curveLoop, bool scaleToMeters = false)
 {
     return(new Polygon(curveLoop.Select(l => l.GetEndPoint(0).ToVector3(scaleToMeters)).ToList()));
 }
예제 #20
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            // We are going to attempt minor repairs for small but reasonable gaps between Line/Line and Line/Arc pairs.  As such, we want to collect the
            // curves before we create the curve loop.

            IList <IFCAnyHandle> segments = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(ifcCurve, "Segments");

            if (segments == null)
            {
                Importer.TheLog.LogError(Id, "Invalid IfcCompositeCurve with no segments.", true);
            }

            // need List<> so that we can AddRange later.
            List <Curve> curveSegments = new List <Curve>();

            foreach (IFCAnyHandle segment in segments)
            {
                IList <Curve> currCurve = ProcessIFCCompositeCurveSegment(segment);
                if (currCurve != null && currCurve.Count != 0)
                {
                    curveSegments.AddRange(currCurve);
                }
            }

            int numSegments = curveSegments.Count;

            if (numSegments == 0)
            {
                Importer.TheLog.LogError(Id, "Invalid IfcCompositeCurve with no segments.", true);
            }

            try
            {
                // We are going to try to reverse or tweak segments as necessary to make the CurveLoop.
                // For each curve, it is acceptable if it can be appended to the end of the existing loop, or prepended to its start,
                // possibly after reversing the curve, and possibly with some tweaking.

                // NOTE: we do not do any checks yet to repair the endpoints of the curveloop to make them closed.
                // NOTE: this is not expected to be perfect with dirty data, but is expected to not change already valid data.

                // curveLoopStartPoint and curveLoopEndPoint will change over time as we add new curves to the start or end of the CurveLoop.
                XYZ curveLoopStartPoint = curveSegments[0].GetEndPoint(0);
                XYZ curveLoopEndPoint   = curveSegments[0].GetEndPoint(1);

                double vertexEps = IFCImportFile.TheFile.Document.Application.VertexTolerance;

                // This is intended to be "relatively large".  The idea here is that the user would rather have the information presented
                // than thrown away because of a gap that is architecturally insignificant.
                double gapVertexEps  = Math.Max(vertexEps, 0.01); // 1/100th of a foot, or 3.048 mm.
                double shortCurveTol = IFCImportFile.TheFile.Document.Application.ShortCurveTolerance;

                // canRepairFirst may change over time, as we may potentially add curves to the start of the CurveLoop.
                bool canRepairFirst = (curveSegments[0] is Line);
                for (int ii = 1; ii < numSegments; ii++)
                {
                    XYZ nextStartPoint = curveSegments[ii].GetEndPoint(0);
                    XYZ nextEndPoint   = curveSegments[ii].GetEndPoint(1);

                    // These will be set below.
                    bool   attachNextSegmentToEnd = false;
                    bool   reverseNextSegment     = false;
                    double minGap = 0.0;

                    // Scoped to prevent distLoopEndPtToNextStartPt and others from being used later on.
                    {
                        // Find the minimum gap between the current curve segment and the existing curve loop.  If it is too large, we will give up.
                        double distLoopEndPtToNextStartPt = curveLoopEndPoint.DistanceTo(nextStartPoint);
                        double distLoopEndPtToNextEndPt   = curveLoopEndPoint.DistanceTo(nextEndPoint);

                        double distLoopStartPtToNextEndPt   = curveLoopStartPoint.DistanceTo(nextEndPoint);
                        double distLoopStartPtToNextStartPt = curveLoopStartPoint.DistanceTo(nextStartPoint);

                        // Determine the minimum gap between the two curves.  If it is too large, we'll give up before trying anything.
                        double minStartGap = Math.Min(distLoopStartPtToNextEndPt, distLoopStartPtToNextStartPt);
                        double minEndGap   = Math.Min(distLoopEndPtToNextStartPt, distLoopEndPtToNextEndPt);

                        minGap = Math.Min(minStartGap, minEndGap);

                        // If the minimum distance between the two curves is greater than gapVertexEps (which is the larger of our two tolerances),
                        // we can't fix the issue.
                        if (minGap > gapVertexEps)
                        {
                            string lengthAsString = UnitFormatUtils.Format(IFCImportFile.TheFile.Document.GetUnits(), UnitType.UT_Length, minGap, true, false);
                            string maxGapAsString = UnitFormatUtils.Format(IFCImportFile.TheFile.Document.GetUnits(), UnitType.UT_Length, gapVertexEps, true, false);
                            throw new InvalidOperationException("IfcCompositeCurve contains a gap of " + lengthAsString +
                                                                " that is greater than the maximum gap size of " + maxGapAsString +
                                                                " and cannot be repaired.");
                        }

                        // We have a possibility to add the segment.  What we do depends on the gap distance.

                        // If the current curve loop's closest end to the next segment is its end (vs. start) point, set attachNextSegmentToEnd to true.
                        attachNextSegmentToEnd = (MathUtil.IsAlmostEqual(distLoopEndPtToNextStartPt, minGap)) ||
                                                 (MathUtil.IsAlmostEqual(distLoopEndPtToNextEndPt, minGap));

                        // We need to reverse the next segment if:
                        // 1. We are attaching the next segment to the end of the curve loop, and the next segment's closest end to the current curve loop is its end (vs. start) point.
                        // 2. We are attaching the next segment to the start of the curve loop, and the next segment's closest end to the current curve loop is its start (vs. end) point.
                        reverseNextSegment = (MathUtil.IsAlmostEqual(distLoopEndPtToNextEndPt, minGap)) ||
                                             (MathUtil.IsAlmostEqual(distLoopStartPtToNextStartPt, minGap));
                    }

                    if (reverseNextSegment)
                    {
                        curveSegments[ii] = curveSegments[ii].CreateReversed();
                        MathUtil.Swap <XYZ>(ref nextStartPoint, ref nextEndPoint);
                    }

                    // If minGap is less than vertexEps, we won't need to do any repairing - just fix the orientation if necessary.
                    if (minGap < vertexEps)
                    {
                        if (attachNextSegmentToEnd)
                        {
                            // Update the curve loop end point to be the end point of the next segment after potentially being reversed.
                            curveLoopEndPoint = nextEndPoint;
                        }
                        else
                        {
                            canRepairFirst      = curveSegments[ii] is Line;
                            curveLoopStartPoint = nextStartPoint;

                            // Update the curve loop start point to be the start point of the next segment, now at the beginning of the loop,
                            // after potentially being reversed.
                            Curve tmpCurve = curveSegments[ii];
                            curveSegments.RemoveAt(ii);
                            curveSegments.Insert(0, tmpCurve);
                        }

                        continue;
                    }

                    // The gap is too big for CurveLoop, but smaller than our maximum tolerance - we will try to fix the gap by extending
                    // one of the line segments around the gap.  If the gap is between two Arcs, we will try to introduce a short
                    // segment between them, as long as the gap is larger than the short curve tolerance.

                    bool canRepairNext     = curveSegments[ii] is Line;
                    bool createdRepairLine = false;

                    if (attachNextSegmentToEnd)
                    {
                        // Update the curve loop end point to be the end point of the next segment after potentially being reversed.
                        XYZ originalCurveLoopEndPoint = curveLoopEndPoint;
                        curveLoopEndPoint = nextEndPoint;
                        if (canRepairNext)
                        {
                            curveSegments[ii] = RepairLineAndReport(Id, originalCurveLoopEndPoint, curveLoopEndPoint, minGap);
                        }
                        else if (curveSegments[ii - 1] is Line) // = canRepairCurrent, only used here.
                        {
                            curveSegments[ii - 1] = RepairLineAndReport(Id, curveSegments[ii - 1].GetEndPoint(0), curveSegments[ii].GetEndPoint(0), minGap);
                        }
                        else
                        {
                            // Can't add a line to fix a gap that is smaller than the short curve tolerance.
                            // In the future, we may fix this gap by intersecting the two curves and extending one of them.
                            if (minGap < shortCurveTol + MathUtil.Eps())
                            {
                                Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that is too short to be repaired by a connecting segment.", true);
                            }

                            try
                            {
                                Line repairLine = Line.CreateBound(originalCurveLoopEndPoint, curveSegments[ii].GetEndPoint(0));
                                curveSegments.Insert(ii, repairLine);
                                ii++; // Skip the repair line as we've already "added" it and the non-linear segment to our growing loop.
                                numSegments++;
                                createdRepairLine = true;
                            }
                            catch
                            {
                                Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that can't be fixed.", true);
                            }
                        }
                    }
                    else
                    {
                        XYZ originalCurveLoopStartPoint = curveLoopStartPoint;
                        curveLoopStartPoint = nextStartPoint;

                        if (canRepairNext)
                        {
                            curveSegments[ii] = RepairLineAndReport(Id, curveLoopStartPoint, originalCurveLoopStartPoint, minGap);
                        }
                        else if (canRepairFirst)
                        {
                            curveSegments[0] = RepairLineAndReport(Id, curveSegments[ii].GetEndPoint(1), curveSegments[0].GetEndPoint(1), minGap);
                        }
                        else
                        {
                            // Can't add a line to fix a gap that is smaller than the short curve tolerance.
                            // In the future, we may fix this gap by intersecting the two curves and extending one of them.
                            if (minGap < shortCurveTol + MathUtil.Eps())
                            {
                                Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that is too short to be repaired by a connecting segment.", true);
                            }

                            Line repairLine = Line.CreateBound(curveSegments[ii].GetEndPoint(1), originalCurveLoopStartPoint);
                            curveSegments.Insert(0, repairLine);
                            ii++; // Skip the repair line as we've already "added" it and the non-linear curve to our growing loop.
                            numSegments++;
                        }

                        // Either canRepairFirst was already true, or canRepairNext was true and we added it to the front of the loop,
                        // or we added a short repair line to the front of the loop.  In any of these cases, the front curve segement of the
                        // loop is now a line segment.
                        if (!canRepairFirst && !canRepairNext && !createdRepairLine)
                        {
                            Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that can't be fixed.", true);
                        }

                        canRepairFirst = true;

                        // Move the curve to the front of the loop.
                        Curve tmpCurve = curveSegments[ii];
                        curveSegments.RemoveAt(ii);
                        curveSegments.Insert(0, tmpCurve);
                    }
                }

                if (CurveLoop == null)
                {
                    CurveLoop = new CurveLoop();
                }

                foreach (Curve curveSegment in curveSegments)
                {
                    CurveLoop.Append(curveSegment);
                }
            }
            catch (Exception ex)
            {
                Importer.TheLog.LogError(Id, ex.Message, true);
            }

            // Try to create the curve representation of this IfcCompositeCurve
            Curve = ConvertCurveLoopIntoSingleCurve(CurveLoop);
        }
예제 #21
0
        /// <summary>
        /// Create Hatch
        /// </summary>
        /// <param name="hatch"></param>
        /// <returns></returns>
        public static Element Create(this Grevit.Types.Hatch hatch)
        {
            // Get all Filled region types
            FilteredElementCollector collector = new FilteredElementCollector(GrevitBuildModel.document).OfClass(typeof(Autodesk.Revit.DB.FilledRegionType));
            
            // Get the View to place the hatch on
            Element viewElement = GrevitBuildModel.document.GetElementByName(typeof(Autodesk.Revit.DB.View), hatch.view);

            // Get the hatch pattern name and set it to solid if the hatch pattern name is invalid
            string patternname = (hatch.pattern == null || hatch.pattern == string.Empty) ? patternname = "Solid fill" : hatch.pattern;

            // Get the fill pattern element and filled region type
            FillPatternElement fillPatternElement = FillPatternElement.GetFillPatternElementByName(GrevitBuildModel.document, FillPatternTarget.Drafting, patternname);
            FilledRegionType filledRegionType = collector.FirstElement() as FilledRegionType;

            // Setup a new curveloop for the outline
            CurveLoop curveLoop = new CurveLoop();
            List<CurveLoop> listOfCurves = new List<CurveLoop>();

            // Get a closed loop from the grevit points
            for (int i = 0; i < hatch.outline.Count; i++)
            {
                int j = i + 1;
                Grevit.Types.Point p1 = hatch.outline[i];
                if (j == hatch.outline.Count) j = 0;
                Grevit.Types.Point p2 = hatch.outline[j];

                Curve cn = Autodesk.Revit.DB.Line.CreateBound(p1.ToXYZ(), p2.ToXYZ());
                curveLoop.Append(cn);
            }

            listOfCurves.Add(curveLoop);
            
            // Create a filled region from the loop
            return FilledRegion.Create(GrevitBuildModel.document, filledRegionType.Id, viewElement.Id, listOfCurves);

        }
예제 #22
0
        private IList <GeometryObject> SplitSweptDiskIntoValidPieces(CurveLoop trimmedDirectrixInWCS, IList <CurveLoop> profileCurveLoops, SolidOptions solidOptions)
        {
            // If we have 0 or 1 curves, there is nothing we can do here.
            int numCurves = trimmedDirectrixInWCS.Count();

            if (numCurves < 2)
            {
                return(null);
            }

            // We will attempt to represent the original description in as few pieces as possible.
            IList <Curve> directrixCurves = new List <Curve>();

            foreach (Curve directrixCurve in trimmedDirectrixInWCS)
            {
                if (directrixCurve == null)
                {
                    numCurves--;
                    if (numCurves < 2)
                    {
                        return(null);
                    }
                    continue;
                }
                directrixCurves.Add(directrixCurve);
            }

            IList <GeometryObject> sweptDiskPieces = new List <GeometryObject>();

            // We will march along the directrix one curve at a time, trying to build a bigger piece of the sweep.  At the point that we throw an exception,
            // we will take the last biggest piece and start over.
            CurveLoop currentCurveLoop    = new CurveLoop();
            Solid     bestSolidSoFar      = null;
            double    pathAttachmentParam = directrixCurves[0].GetEndParameter(0);

            for (int ii = 0; ii < numCurves; ii++)
            {
                currentCurveLoop.Append(directrixCurves[ii]);
                try
                {
                    Solid currentSolid = GeometryCreationUtilities.CreateSweptGeometry(currentCurveLoop, 0, pathAttachmentParam, profileCurveLoops,
                                                                                       solidOptions);
                    bestSolidSoFar = currentSolid;
                }
                catch
                {
                    if (bestSolidSoFar != null)
                    {
                        sweptDiskPieces.Add(bestSolidSoFar);
                        bestSolidSoFar = null;
                    }
                }

                // This should only happen as a result of the catch loop above.  We want to protect against the case where one or more pieces of the sweep
                // are completely invalid.
                while (bestSolidSoFar == null && (ii < numCurves))
                {
                    try
                    {
                        currentCurveLoop = new CurveLoop();
                        currentCurveLoop.Append(directrixCurves[ii]);
                        profileCurveLoops = CreateProfileCurveLoopsForDirectrix(directrixCurves[ii], out pathAttachmentParam);

                        Solid currentSolid = GeometryCreationUtilities.CreateSweptGeometry(currentCurveLoop, 0, pathAttachmentParam, profileCurveLoops,
                                                                                           solidOptions);
                        bestSolidSoFar = currentSolid;
                        break;
                    }
                    catch
                    {
                        ii++;
                    }
                }
            }

            return(sweptDiskPieces);
        }
예제 #23
0
        /// <summary>
        /// Finds parent handle from opening CurveLoop and parent CurveLoops.
        /// </summary>
        /// <param name="elementHandles">The parent handles.</param>
        /// <param name="curveLoops">The parent CurveLoops.</param>
        /// <param name="openingLoop">The opening CurveLoop.</param>
        /// <returns>The parent handle.</returns>
        private static IFCAnyHandle FindParentHandle(IList<IFCAnyHandle> elementHandles, IList<CurveLoop> curveLoops, CurveLoop openingLoop)
        {
            // first one is roof handle, others are slabs
            if (elementHandles.Count != curveLoops.Count + 1)
                return null;

            for (int ii = 0; ii < curveLoops.Count; ii++)
            {
                if (GeometryUtil.CurveLoopsInside(openingLoop, curveLoops[ii]) || GeometryUtil.CurveLoopsIntersect(openingLoop, curveLoops[ii]))
                {
                    return elementHandles[ii + 1];
                }
            }
            return elementHandles[0];
        }
예제 #24
0
        /// <summary>
        ///  Exports a roof or floor as a container of multiple roof slabs.  Returns the handle, if successful.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="element">The roof or floor element.</param>
        /// <param name="geometry">The geometry of the element.</param>
        /// <param name="productWrapper">The product wrapper.</param>
        /// <returns>The roof handle.</returns>
        /// <remarks>For floors, if there is only one component, return null, as we do not want to create a container.</remarks>
        public static IFCAnyHandle ExportRoofOrFloorAsContainer(ExporterIFC exporterIFC,
                                                                Element element, GeometryElement geometry, ProductWrapper productWrapper)
        {
            IFCFile file = exporterIFC.GetFile();

            // We support ExtrusionRoofs, FootPrintRoofs, and Floors only.
            bool elementIsRoof  = (element is ExtrusionRoof) || (element is FootPrintRoof);
            bool elementIsFloor = (element is Floor);

            if (!elementIsRoof && !elementIsFloor)
            {
                return(null);
            }

            string            subSlabType    = null;
            IFCExportInfoPair roofExportType = ExporterUtil.GetProductExportType(exporterIFC, element, out _);

            if (roofExportType.IsUnKnown)
            {
                IFCEntityType elementClassTypeEnum =
                    elementIsFloor ? IFCEntityType.IfcSlab: IFCEntityType.IfcRoof;
                roofExportType = new IFCExportInfoPair(elementClassTypeEnum, "");
            }
            else
            {
                if (elementIsFloor)
                {
                    subSlabType = "FLOOR";
                }
                else if (elementIsRoof)
                {
                    subSlabType = "ROOF";
                }
            }

            // Check the intended IFC entity or type name is in the exclude list specified in the UI
            if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(roofExportType.ExportType))
            {
                return(null);
            }

            Document doc = element.Document;

            using (SubTransaction tempPartTransaction = new SubTransaction(doc))
            {
                using (IFCTransaction transaction = new IFCTransaction(file))
                {
                    MaterialLayerSetInfo layersetInfo = new MaterialLayerSetInfo(exporterIFC, element, productWrapper);
                    bool hasLayers = false;
                    if (layersetInfo.MaterialIds.Count > 1)
                    {
                        hasLayers = true;
                    }
                    bool exportByComponents = ExporterCacheManager.ExportOptionsCache.ExportAs4ReferenceView && hasLayers;

                    // Check for containment override
                    IFCAnyHandle overrideContainerHnd = null;
                    ElementId    overrideContainerId  = ParameterUtil.OverrideContainmentParameter(exporterIFC, element, out overrideContainerHnd);

                    // We want to delay creating entity handles until as late as possible, so that if we abort the IFC transaction,
                    // we don't have to delete elements.  This is both for performance reasons and to potentially extend the number
                    // of projects that can be exported by reducing (a small amount) of waste.
                    IList <HostObjectSubcomponentInfo> hostObjectSubcomponents = null;
                    try
                    {
                        hostObjectSubcomponents = ExporterIFCUtils.ComputeSubcomponents(element as HostObject);
                    }
                    catch
                    {
                        return(null);
                    }

                    if (hostObjectSubcomponents == null)
                    {
                        return(null);
                    }

                    int numSubcomponents = hostObjectSubcomponents.Count;
                    if (numSubcomponents == 0 || (elementIsFloor && numSubcomponents == 1))
                    {
                        return(null);
                    }

                    using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element, null, null, overrideContainerId, overrideContainerHnd))
                    {
                        IFCAnyHandle localPlacement = setter.LocalPlacement;


                        IFCAnyHandle hostObjectHandle = null;
                        try
                        {
                            using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData())
                            {
                                IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle;
                                extrusionCreationData.SetLocalPlacement(localPlacement);
                                extrusionCreationData.ReuseLocalPlacement = true;

                                using (TransformSetter trfSetter = TransformSetter.Create())
                                {
                                    IList <GeometryObject> geometryList = new List <GeometryObject>();
                                    geometryList.Add(geometry);
                                    trfSetter.InitializeFromBoundingBox(exporterIFC, geometryList, extrusionCreationData);

                                    IFCAnyHandle prodRepHnd = null;

                                    string elementGUID = GUIDUtil.CreateGUID(element);

                                    hostObjectHandle = IFCInstanceExporter.CreateGenericIFCEntity(
                                        roofExportType, exporterIFC, element, elementGUID, ownerHistory,
                                        localPlacement, prodRepHnd);

                                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(hostObjectHandle))
                                    {
                                        return(null);
                                    }

                                    IList <IFCAnyHandle> elementHandles = new List <IFCAnyHandle>();
                                    elementHandles.Add(hostObjectHandle);

                                    // If element is floor, then the profile curve loop of hostObjectSubComponent is computed from the top face of the floor
                                    // else if element is roof, then the profile curve loop is taken from the bottom face of the roof instead
                                    XYZ extrusionDir = elementIsFloor ? new XYZ(0, 0, -1) : new XYZ(0, 0, 1);

                                    ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                                    IList <IFCAnyHandle> slabHandles = new List <IFCAnyHandle>();

                                    IList <CurveLoop> hostObjectOpeningLoops = new List <CurveLoop>();
                                    double            maximumScaledDepth     = 0.0;

                                    using (IFCExtrusionCreationData slabExtrusionCreationData = new IFCExtrusionCreationData())
                                    {
                                        slabExtrusionCreationData.SetLocalPlacement(extrusionCreationData.GetLocalPlacement());
                                        slabExtrusionCreationData.ReuseLocalPlacement = false;
                                        slabExtrusionCreationData.ForceOffset         = true;

                                        int loopNum         = 0;
                                        int subElementStart = elementIsRoof ? (int)IFCRoofSubElements.RoofSlabStart : (int)IFCSlabSubElements.SubSlabStart;

                                        foreach (HostObjectSubcomponentInfo hostObjectSubcomponent in hostObjectSubcomponents)
                                        {
                                            trfSetter.InitializeFromBoundingBox(exporterIFC, geometryList, slabExtrusionCreationData);
                                            Plane     plane = hostObjectSubcomponent.GetPlane();
                                            Transform lcs   = GeometryUtil.CreateTransformFromPlane(plane);

                                            IList <CurveLoop> curveLoops = new List <CurveLoop>();

                                            CurveLoop slabCurveLoop = hostObjectSubcomponent.GetCurveLoop();
                                            curveLoops.Add(slabCurveLoop);
                                            double slope                        = Math.Abs(plane.Normal.Z);
                                            double scaledDepth                  = UnitUtil.ScaleLength(hostObjectSubcomponent.Depth);
                                            double scaledExtrusionDepth         = scaledDepth * slope;
                                            IList <IFCAnyHandle> shapeReps      = new List <IFCAnyHandle>();
                                            IFCAnyHandle         prodDefShape   = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps);
                                            IFCAnyHandle         contextOfItems = exporterIFC.Get3DContextHandle("Body");
                                            string representationType           = ShapeRepresentationType.SweptSolid.ToString();

                                            // Create representation items based on the layers
                                            // Because in this case, the Roof components are not derived from Parts, but by "splitting" geometry part that can be extruded,
                                            //    the creation of the Items for IFC4RV will be different by using "manual" split based on the layer thickness
                                            HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>();
                                            if (!exportByComponents)
                                            {
                                                IFCAnyHandle itemShapeRep = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, lcs, extrusionDir, scaledExtrusionDepth, false);
                                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(itemShapeRep))
                                                {
                                                    productWrapper.ClearInternalHandleWrapperData(element);
                                                    return(null);
                                                }
                                                ElementId matId = HostObjectExporter.GetFirstLayerMaterialId(element as HostObject);
                                                BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, element.Document, false, itemShapeRep, matId);
                                                bodyItems.Add(itemShapeRep);
                                            }
                                            else
                                            {
                                                List <MaterialLayerSetInfo.MaterialInfo> MaterialIds = layersetInfo.MaterialIds;
                                                ElementId typeElemId = element.GetTypeId();
                                                // From CollectMaterialLayerSet() Roofs with no components are only allowed one material. It arbitrarily chooses the thickest material.
                                                // To be consistant with Roof(as Slab), we will reverse the order.
                                                IFCAnyHandle materialLayerSet         = ExporterCacheManager.MaterialSetCache.FindLayerSet(typeElemId);
                                                bool         materialHandleIsNotValid = IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet);
                                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet) || materialHandleIsNotValid)
                                                {
                                                    MaterialIds.Reverse();
                                                }

                                                double scaleProj = extrusionDir.DotProduct(plane.Normal);
                                                foreach (MaterialLayerSetInfo.MaterialInfo matLayerInfo in MaterialIds)
                                                {
                                                    double       itemExtrDepth       = matLayerInfo.m_matWidth;
                                                    double       scaledItemExtrDepth = UnitUtil.ScaleLength(itemExtrDepth) * slope;
                                                    IFCAnyHandle itemShapeRep        = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, lcs, extrusionDir, scaledItemExtrDepth, false);
                                                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(itemShapeRep))
                                                    {
                                                        productWrapper.ClearInternalHandleWrapperData(element);
                                                        return(null);
                                                    }

                                                    BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, element.Document, false, itemShapeRep, matLayerInfo.m_baseMatId);

                                                    bodyItems.Add(itemShapeRep);
                                                    RepresentationUtil.CreateRepForShapeAspect(exporterIFC, element, prodDefShape, representationType, matLayerInfo.m_layerName, itemShapeRep);

                                                    XYZ offset = new XYZ(0, 0, itemExtrDepth / scaleProj); // offset is calculated as extent in the direction of extrusion
                                                    lcs.Origin += offset;
                                                }
                                            }

                                            IFCAnyHandle shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, catId, contextOfItems, bodyItems, null);
                                            shapeReps.Add(shapeRep);
                                            IFCAnyHandleUtil.SetAttribute(prodDefShape, "Representations", shapeReps);

                                            // We could replace the code below to just use the newer, and better,
                                            // GenerateIFCGuidFrom.  The code below maintains compatibility with older
                                            // versions while generating a stable GUID for all slabs (in the unlikely
                                            // case that we have more than 255 of them).
                                            string slabGUID = (loopNum < 256) ?
                                                              GUIDUtil.CreateSubElementGUID(element, subElementStart + loopNum) :
                                                              GUIDUtil.GenerateIFCGuidFrom(element, "Slab: " + loopNum.ToString());

                                            IFCAnyHandle slabPlacement = ExporterUtil.CreateLocalPlacement(file, slabExtrusionCreationData.GetLocalPlacement(), null);
                                            IFCAnyHandle slabHnd       = IFCInstanceExporter.CreateSlab(exporterIFC, element, slabGUID, ownerHistory,
                                                                                                        slabPlacement, prodDefShape, subSlabType);
                                            IFCExportInfoPair exportType = new IFCExportInfoPair(IFCEntityType.IfcSlab, subSlabType);

                                            //slab quantities
                                            slabExtrusionCreationData.ScaledLength         = scaledExtrusionDepth;
                                            slabExtrusionCreationData.ScaledArea           = UnitUtil.ScaleArea(UnitUtil.ScaleArea(hostObjectSubcomponent.AreaOfCurveLoop));
                                            slabExtrusionCreationData.ScaledOuterPerimeter = UnitUtil.ScaleLength(curveLoops[0].GetExactLength());
                                            slabExtrusionCreationData.Slope = UnitUtil.ScaleAngle(MathUtil.SafeAcos(Math.Abs(slope)));

                                            IFCExportInfoPair slabRoofExportType = new IFCExportInfoPair(IFCEntityType.IfcSlab, subSlabType);
                                            productWrapper.AddElement(null, slabHnd, setter, slabExtrusionCreationData, false, slabRoofExportType);

                                            // Create type
                                            IFCAnyHandle slabRoofTypeHnd = ExporterUtil.CreateGenericTypeFromElement(element, slabRoofExportType, exporterIFC.GetFile(), ownerHistory, subSlabType, productWrapper);
                                            ExporterCacheManager.TypeRelationsCache.Add(slabRoofTypeHnd, slabHnd);

                                            elementHandles.Add(slabHnd);
                                            slabHandles.Add(slabHnd);

                                            hostObjectOpeningLoops.Add(slabCurveLoop);
                                            maximumScaledDepth = Math.Max(maximumScaledDepth, scaledDepth);
                                            loopNum++;

                                            ExporterUtil.AddIntoComplexPropertyCache(slabHnd, layersetInfo);

                                            // Create material association here
                                            if (layersetInfo != null && !IFCAnyHandleUtil.IsNullOrHasNoValue(layersetInfo.MaterialLayerSetHandle))
                                            {
                                                CategoryUtil.CreateMaterialAssociation(slabHnd, layersetInfo.MaterialLayerSetHandle);
                                            }
                                        }
                                    }

                                    productWrapper.AddElement(element, hostObjectHandle, setter, extrusionCreationData, true, roofExportType);

                                    ExporterUtil.RelateObjects(exporterIFC, null, hostObjectHandle, slabHandles);

                                    OpeningUtil.AddOpeningsToElement(exporterIFC, elementHandles, hostObjectOpeningLoops, element, null, maximumScaledDepth,
                                                                     null, setter, localPlacement, productWrapper);

                                    transaction.Commit();
                                    return(hostObjectHandle);
                                }
                            }
                        }
                        catch
                        {
                            // SOmething wrong with the above process, unable to create the extrusion data. Reset any internal handles that may have been partially created since they are not committed
                            productWrapper.ClearInternalHandleWrapperData(element);
                            return(null);
                        }
                        finally
                        {
                            exporterIFC.ClearFaceWithElementHandleMap();
                        }
                    }
                }
            }
        }
예제 #25
0
 private static IFCRange GetExtrusionRangeOfCurveLoop(CurveLoop loop, XYZ extrusionDirection)
 {
     IFCRange range = new IFCRange();
     bool init = false;
     foreach (Curve curve in loop)
     {
         if (!init)
         {
             if (curve.IsBound)
             {
                 IList<XYZ> coords = curve.Tessellate();
                 foreach (XYZ coord in coords)
                 {
                     double val = coord.DotProduct(extrusionDirection);
                     if (!init)
                     {
                         range.Start = val;
                         range.End = val;
                         init = true;
                     }
                     else
                     {
                         range.Start = Math.Min(range.Start, val);
                         range.End = Math.Max(range.End, val);
                     }
                 }
             }
             else
             {
                 double val = curve.get_EndPoint(0).DotProduct(extrusionDirection);
                 range.Start = val;
                 range.End = val;
                 init = true;
             }
         }
         else
         {
             double val = curve.get_EndPoint(0).DotProduct(extrusionDirection);
             range.Start = Math.Min(range.Start, val);
             range.End = Math.Max(range.End, val);
         }
     }
     return range;
 }
        /// <summary>
        /// This method takes the solidsList and clips all of its solids between the given range.
        /// </summary>
        /// <param name="elem">
        /// The Element from which we obtain our BoundingBoxXYZ.
        /// </param>
        /// <param name="geomElem">
        /// The top-level GeometryElement from which to gather X and Y coordinates for the intersecting solid.
        /// </param>
        /// <param name="range">
        /// The IFCRange whose Z values we use to create an intersecting solid to clip the solids in this class's internal solidsList.
        /// If range boundaries are equal, method returns, performing no clippings.
        /// </param>
        public void ClipSolidsList(GeometryElement geomElem, IFCRange range)
        {
            if (geomElem == null)
            {
                throw new ArgumentNullException("geomElemToUse");
            }
            if (MathUtil.IsAlmostEqual(range.Start, range.End) || solidsList.Count == 0)
            {
                return;
            }

            double bottomZ;
            double boundDifference;

            if (range.Start < range.End)
            {
                bottomZ         = range.Start;
                boundDifference = range.End - range.Start;
            }
            else
            {
                bottomZ         = range.End;
                boundDifference = range.Start - range.End;
            }

            // create a new solid using the X and Y of the bounding box on the top level GeometryElement and the Z of the IFCRange
            BoundingBoxXYZ elemBoundingBox = geomElem.GetBoundingBox();
            XYZ            pointA          = new XYZ(elemBoundingBox.Min.X, elemBoundingBox.Min.Y, bottomZ);
            XYZ            pointB          = new XYZ(elemBoundingBox.Max.X, elemBoundingBox.Min.Y, bottomZ);
            XYZ            pointC          = new XYZ(elemBoundingBox.Max.X, elemBoundingBox.Max.Y, bottomZ);
            XYZ            pointD          = new XYZ(elemBoundingBox.Min.X, elemBoundingBox.Max.Y, bottomZ);

            List <Curve> perimeter = new List <Curve>();

            perimeter.Add(Line.CreateBound(pointA, pointB));
            perimeter.Add(Line.CreateBound(pointB, pointC));
            perimeter.Add(Line.CreateBound(pointC, pointD));
            perimeter.Add(Line.CreateBound(pointD, pointA));

            List <CurveLoop> boxPerimeterList = new List <CurveLoop>();

            boxPerimeterList.Add(CurveLoop.Create(perimeter));
            Solid intersectionSolid = GeometryCreationUtilities.CreateExtrusionGeometry(boxPerimeterList, XYZ.BasisZ, boundDifference);

            // cycle through the elements in solidsList and intersect them against intersectionSolid to create a new list
            List <Solid> clippedSolidsList = new List <Solid>();
            Solid        currSolid;

            foreach (Solid solid in solidsList)
            {
                try
                {
                    // ExecuteBooleanOperation can throw if it fails.  In this case, just ignore the clipping.
                    currSolid = BooleanOperationsUtils.ExecuteBooleanOperation(solid, intersectionSolid, BooleanOperationsType.Intersect);
                    if (currSolid != null && currSolid.Volume != 0)
                    {
                        clippedSolidsList.Add(currSolid);
                    }
                }
                catch
                {
                }
            }
            solidsList = clippedSolidsList;
        }
예제 #27
0
        /// <summary>
        /// Creates an open or closed CurveLoop from a list of vertices.
        /// </summary>
        /// <param name="pointXYZs">The list of vertices.</param>
        /// <param name="points">The optional list of IFCAnyHandles that generated the vertices, used solely for error reporting.</param>
        /// <param name="id">The id of the IFCAnyHandle associated with the CurveLoop.</param>
        /// <param name="isClosedLoop">True if the vertices represent a closed loop, false if not.</param>
        /// <returns>The new curve loop.</returns>
        /// <remarks>If isClosedLoop is true, there will be pointsXyz.Count line segments.  Otherwise, there will be pointsXyz.Count-1.</remarks>
        public static CurveLoop CreatePolyCurveLoop(IList<XYZ> pointXYZs, IList<IFCAnyHandle> points, int id, bool isClosedLoop)
        {
            int numPoints = pointXYZs.Count;
            if (numPoints < 2)
                return null;

            IList<int> badIds = new List<int>();

            int numMinPoints = isClosedLoop ? 3 : 2;
            
            // Check distance between points; remove too-close points, and warn if result is non-collinear.
            // Always include first point.
            IList<XYZ> finalPoints = new List<XYZ>();
            finalPoints.Add(pointXYZs[0]);
            int numNewPoints = 1;
            for (int ii = 1; ii < numPoints; ii++)
            {
                if (IFCGeometryUtil.LineSegmentIsTooShort(finalPoints[numNewPoints - 1], pointXYZs[ii]))
                {
                    if (points != null)
                        badIds.Add(points[ii].StepId);
                    else
                        badIds.Add(ii+1);
                }
                else
                {
                    finalPoints.Add(pointXYZs[ii]);
                    numNewPoints++;
                }
            }

            // Check final segment; if too short, delete 2nd to last point.
            if (isClosedLoop)
            {
                if (IFCGeometryUtil.LineSegmentIsTooShort(finalPoints[numNewPoints - 1], pointXYZs[0]))
                {
                    finalPoints.RemoveAt(numNewPoints - 1);
                    numNewPoints--;
                }
            }

            // This can be a very common warning, so we will restrict to verbose logging.
            if (Importer.TheOptions.VerboseLogging)
            {
                if (badIds.Count > 0)
                {
                    int count = badIds.Count;
                    string msg = null;
                    if (count == 1)
                    {
                        msg = "Polyline had 1 point that was too close to one of its neighbors, removing point: #" + badIds[0] + ".";
                    }
                    else
                    {
                        msg = "Polyline had " + count + " points that were too close to one of their neighbors, removing points:";
                        foreach (int badId in badIds)
                            msg += " #" + badId;
                        msg += ".";
                    }
                    IFCImportFile.TheLog.LogWarning(id, msg, false);
                }
            }

            if (numNewPoints < numMinPoints)
            {
                if (Importer.TheOptions.VerboseLogging)
                {
                    string msg = "PolyCurve had " + numNewPoints + " point(s) after removing points that were too close, expected at least " + numMinPoints + ", ignoring.";
                    IFCImportFile.TheLog.LogWarning(id, msg, false);
                }
                return null;
            }

            CurveLoop curveLoop = new CurveLoop();
            for (int ii = 0; ii < numNewPoints - 1; ii++)
                curveLoop.Append(Line.CreateBound(finalPoints[ii], finalPoints[ii + 1]));
            if (isClosedLoop)
                curveLoop.Append(Line.CreateBound(finalPoints[numNewPoints - 1], finalPoints[0]));

            return curveLoop;
        }
예제 #28
0
        private void ProcessIFCPolyline(IFCAnyHandle ifcCurve)
        {
            IList<IFCAnyHandle> points = IFCAnyHandleUtil.GetAggregateInstanceAttribute<List<IFCAnyHandle>>(ifcCurve, "Points");
            int numPoints = points.Count;
            if (numPoints < 2)
            {
                string msg = "IfcPolyLine had " + numPoints + ", expected at least 2, ignoring";
                IFCImportFile.TheLog.LogError(Id, msg, false);
                return;
            }

            IList<XYZ> pointXYZs = new List<XYZ>();
            foreach (IFCAnyHandle point in points)
            {
                XYZ pointXYZ = IFCPoint.ProcessScaledLengthIFCCartesianPoint(point);
                pointXYZs.Add(pointXYZ);
            }

            CurveLoop = IFCGeometryUtil.CreatePolyCurveLoop(pointXYZs, points, Id, false);
        }
        private IList<GeometryObject> SplitSweptDiskIntoValidPieces(CurveLoop trimmedDirectrixInWCS, IList<CurveLoop> profileCurveLoops, SolidOptions solidOptions)
        {
           // If we have 0 or 1 curves, there is nothing we can do here.
           int numCurves = trimmedDirectrixInWCS.Count();
           if (numCurves < 2)
              return null;

           // We will attempt to represent the original description in as few pieces as possible.  
           IList<Curve> directrixCurves = new List<Curve>();
           foreach (Curve directrixCurve in trimmedDirectrixInWCS)
           {
              if (directrixCurve == null)
              {
                 numCurves--;
                 if (numCurves < 2)
                    return null;
                 continue;
              }
              directrixCurves.Add(directrixCurve);
           }

           IList<GeometryObject> sweptDiskPieces = new List<GeometryObject>();

           // We will march along the directrix one curve at a time, trying to build a bigger piece of the sweep.  At the point that we throw an exception,
           // we will take the last biggest piece and start over.
           CurveLoop currentCurveLoop = new CurveLoop();
           Solid bestSolidSoFar = null;
           double pathAttachmentParam = directrixCurves[0].GetEndParameter(0);

           for (int ii = 0; ii < numCurves; ii++)
           {
              currentCurveLoop.Append(directrixCurves[ii]);
              try
              {
                 Solid currentSolid = GeometryCreationUtilities.CreateSweptGeometry(currentCurveLoop, 0, pathAttachmentParam, profileCurveLoops,
                    solidOptions);
                 bestSolidSoFar = currentSolid;
              }
              catch
              {
                 if (bestSolidSoFar != null)
                 {
                    sweptDiskPieces.Add(bestSolidSoFar);
                    bestSolidSoFar = null;
                 }
              }

              // This should only happen as a result of the catch loop above.  We want to protect against the case where one or more pieces of the sweep 
              // are completely invalid.
              while (bestSolidSoFar == null && (ii < numCurves))
              {
                 try
                 {
                    currentCurveLoop = new CurveLoop();
                    currentCurveLoop.Append(directrixCurves[ii]);
                    profileCurveLoops = CreateProfileCurveLoopsForDirectrix(directrixCurves[ii], out pathAttachmentParam);

                    Solid currentSolid = GeometryCreationUtilities.CreateSweptGeometry(currentCurveLoop, 0, pathAttachmentParam, profileCurveLoops,
                       solidOptions);
                    bestSolidSoFar = currentSolid;
                    break;
                 }
                 catch
                 {
                    ii++;
                 }
              }
           }

           return sweptDiskPieces;
        }
      /// <summary>
      /// Create a curve representation of this IFCCompositeCurve from a curveloop
      /// </summary>
      /// <param name="curveLoop">The curveloop</param>
      /// <returns>A Revit curve that is made by appending every curve in the given curveloop, if possible</returns>
      private Curve ConvertCurveLoopIntoSingleCurve(CurveLoop curveLoop)
      {
         if (curveLoop == null)
         {
            return null;
         }

         CurveLoopIterator curveIterator = curveLoop.GetCurveLoopIterator();
         Curve firstCurve = curveIterator.Current;
         Curve returnCurve = null;

         // We only connect the curves if they are Line, Arc or Ellipse
         if (!((firstCurve is Line) || (firstCurve is Arc) || (firstCurve is Ellipse)))
         {
            return null;
         }

         XYZ firstStartPoint = firstCurve.GetEndPoint(0);

         Curve currentCurve = null;
         if (firstCurve is Line)
         {
            Line firstLine = firstCurve as Line;
            while(curveIterator.MoveNext())
            {
               currentCurve = curveIterator.Current;
               if (!(currentCurve is Line))
               {
                  return null;
               }
               Line currentLine = currentCurve as Line;

               if (!(firstLine.Direction.IsAlmostEqualTo(currentLine.Direction)))
               {
                  return null;
               }
            }
            returnCurve = Line.CreateBound(firstStartPoint, currentCurve.GetEndPoint(1));
         }
         else if (firstCurve is Arc)
         {
            Arc firstArc = firstCurve as Arc;
            XYZ firstCurveNormal = firstArc.Normal;

            while(curveIterator.MoveNext())
            {
               currentCurve = curveIterator.Current;
               if (!(currentCurve is Arc))
               {
                   return null;
               }

               XYZ currentStartPoint = currentCurve.GetEndPoint(0);
               XYZ currentEndPoint = currentCurve.GetEndPoint(1);

               Arc currentArc = currentCurve as Arc;
               XYZ currentCenter = currentArc.Center;
               double currentRadius = currentArc.Radius;
               XYZ currentNormal = currentArc.Normal;

               // We check if this circle is similar to the first circle by checking that they have the same center, same radius,
               // and lie on the same plane
               if (!(currentCenter.IsAlmostEqualTo(firstArc.Center) && MathUtil.IsAlmostEqual(currentRadius, firstArc.Radius)))
               {
                  return null;
               }
               if (!MathUtil.IsAlmostEqual(Math.Abs(currentNormal.DotProduct(firstCurveNormal)), 1))
               {
                  return null;
               }
            }
            // If all of the curve segments are part of the same circle, then the returning curve will be a circle bounded
            // by the start point of the first curve and the end point of the last curve.
            XYZ lastPoint = currentCurve.GetEndPoint(1);
            if (lastPoint.IsAlmostEqualTo(firstStartPoint))
            {
               firstCurve.MakeUnbound();
            }
            else
            {
               double startParameter = firstArc.GetEndParameter(0);
               double endParameter = firstArc.Project(lastPoint).Parameter;

               if (endParameter < startParameter)
                  endParameter += Math.PI * 2;

               firstCurve.MakeBound(startParameter, endParameter);
            }
            returnCurve = firstCurve;
            
         }
         else if (firstCurve is Ellipse)
         {
            Ellipse firstEllipse = firstCurve as Ellipse;
            double radiusX = firstEllipse.RadiusX;
            double radiusY = firstEllipse.RadiusY;
            XYZ xDirection = firstEllipse.XDirection;
            XYZ yDirection = firstEllipse.YDirection;
            XYZ firstCurveNormal = firstEllipse.Normal;

            while(curveIterator.MoveNext())
            {
               currentCurve = curveIterator.Current;
               if (!(currentCurve is Ellipse))
                  return null;

               XYZ currentStartPoint = currentCurve.GetEndPoint(0);
               XYZ currentEndPoint = currentCurve.GetEndPoint(1);

               Ellipse currentEllipse = currentCurve as Ellipse;
               XYZ currentCenter = currentEllipse.Center;

               double currentRadiusX = currentEllipse.RadiusX;
               double currentRadiusY = currentEllipse.RadiusY;
               XYZ currentXDirection = currentEllipse.XDirection;
               XYZ currentYDirection = currentEllipse.YDirection;

               XYZ currentNormal = currentEllipse.Normal;

               if (!MathUtil.IsAlmostEqual(Math.Abs(currentNormal.DotProduct(firstCurveNormal)), 1))
               {
                  return null;
               }

               // We determine whether this ellipse is the same as the initial ellipse by checking if their centers and corresponding
               // radiuses as well as radius directions are the same or permutations of each other.
               if (!currentCenter.IsAlmostEqualTo(firstEllipse.Center))
               {
                  return null;
               }

               // Checks if the corresponding radius and radius direction are the same
               if (MathUtil.IsAlmostEqual(radiusX, currentRadiusX))
               {
                  if (!(MathUtil.IsAlmostEqual(radiusY, currentRadiusY) && currentXDirection.IsAlmostEqualTo(xDirection) && currentYDirection.IsAlmostEqualTo(yDirection)))
                  {
                     return null;
                  }
               }
               // Checks if the corresponding radiuses and radius directions are permutations of each other
               else if (MathUtil.IsAlmostEqual(radiusX, currentRadiusY))
               {
                  if (!(MathUtil.IsAlmostEqual(radiusY, currentRadiusX) && currentXDirection.IsAlmostEqualTo(yDirection) && currentYDirection.IsAlmostEqualTo(xDirection)))
                  {
                     return null;
                  }
               }
               else
               {
                  return null;
               }
            }

            // If all of the curve segments are part of the same ellipse then the returning curve will be the ellipse whose start point is the start 
            // point of the first curve and the end point is the end point of the last curve
            XYZ lastPoint = currentCurve.GetEndPoint(1);
            if (lastPoint.IsAlmostEqualTo(firstStartPoint))
            {
               firstCurve.MakeUnbound();
            }
            else
            {
               double startParameter = firstEllipse.GetEndParameter(0);
               double endParameter = firstEllipse.Project(lastPoint).Parameter;

               if (endParameter < startParameter)
               {
                  endParameter += Math.PI * 2;
               }
               firstCurve.MakeBound(startParameter, endParameter);
            }
            returnCurve = firstCurve;
         }
         
         return returnCurve;
      }
예제 #31
0
        private List <List <Floor> > createLiningConcreteAsFloor2(Document doc, ElementId myFoundtionId, string nameFamily, double offsetValue, bool isCutting)

        {
            Element myFoundation = doc.GetElement(myFoundtionId) as Element;

            //Get level from elemet
            Level myLevel = doc.GetElement(myFoundation.LevelId) as Level;

            //Get geometry from element
            GeometryElement geometryElement = myFoundation.get_Geometry(new Options());

            //Get list Of face (with normal vector = xyz(0,0,-1);

            List <Face> myListBottomFace = new List <Face>();

            using (Transaction myTrans = new Transaction(doc, "fil face of foundation"))
            {
                myTrans.Start();
                UV myPoint = new UV(0, 0);

                foreach (GeometryObject geometryObject in geometryElement)
                {
                    if (geometryObject is Solid)
                    {
                        Solid solid     = geometryObject as Solid;
                        XYZ   myNormVec = new XYZ();
                        foreach (Face myFace in solid.Faces)
                        {
                            myNormVec = myFace.ComputeNormal(myPoint);

                            // If normal vector of face has Z value == -1 add to list
                            if (Math.Round(myNormVec.Z, 1) == -1.0)
                            {
                                myListBottomFace.Add(myFace);
                            }
                        }
                    }
                }
                myTrans.Commit();
            }

            // Now We has a list of face (with normal vector = (0,0,-1)

            //Save floor to a list

            List <Floor> myListLining = new List <Floor>();

            // List Floor cutting
            List <Floor> myListLiningCutting = new List <Floor>();


            using (Transaction trans = new Transaction(doc, "abc"))
            {
                trans.Start();
                foreach (Face myPickedFace in myListBottomFace)
                {
                    //Get Nomarl vector
                    XYZ myNorVecFace = myPickedFace.ComputeNormal(new UV(0, 0));
                    List <CurveLoop> myListCurvefromFace = myPickedFace.GetEdgesAsCurveLoops() as List <CurveLoop>;


                    CurveArray myBoundaFloor = new CurveArray();

                    foreach (CurveLoop myCurLoop in myListCurvefromFace)
                    {
                        if (myFoundation.Category.Name != "Structural Framing")
                        {
                            // Offset For Slab
                            CurveLoop curOffset = CurveLoop.CreateViaOffset(myCurLoop, offsetValue, myNorVecFace);
                            //TaskDialog.Show("abc", "xyz: " +curOffset.GetPlane().Normal.ToString());

                            foreach (Curve myCur in curOffset)
                            {
                                myBoundaFloor.Append(myCur);
                            }
                        }

                        else
                        {
                            List <double> myOffsetDist = getOffsetDis(myCurLoop, offsetValue);


                            CurveLoop curOffset = CurveLoop.CreateViaOffset(myCurLoop, myOffsetDist, myNorVecFace);
                            //TaskDialog.Show("abc", "xyz: " +curOffset.GetPlane().Normal.ToString());

                            foreach (Curve myCur in curOffset)
                            {
                                myBoundaFloor.Append(myCur);
                            }
                        }
                    }

                    FloorType floorType
                        = new FilteredElementCollector(doc)
                          .OfClass(typeof(FloorType))
                          .OfCategory(BuiltInCategory.OST_Floors)
                          .First <Element>(f => f.Name.Equals(nameFamily)) as FloorType;

                    //Floor myLining =  doc.Create.NewFoundationSlab(myBoundaFloor, floorType, myLevel, true, new XYZ(0,0,1));

                    //Floor myLining =  doc.Create.NewFloor(myBoundaFloor, floorType, myLevel, true, new XYZ(0,0,1));

                    Floor myLining = doc.Create.NewFloor(myBoundaFloor, floorType, myLevel, true, new XYZ(0, 0, 1));


                    // Cutting if foundation is beam

                    if (isCutting)
                    {
                        myListLiningCutting.Add(myLining);
                    }

                    myListLining.Add(myLining);
                }
                trans.Commit();
            }

            // Switch Joint
            List <List <Floor> > myListListFloor = new List <List <Floor> >()
            {
                myListLining, myListLiningCutting
            };

            return(myListListFloor);
        }
예제 #32
0
        // This routine may return null geometry for one of three reasons:
        // 1. Invalid input.
        // 2. No IfcMaterialLayerUsage.
        // 3. The IfcMaterialLayerUsage isn't handled.
        // If the reason is #1 or #3, we want to warn the user.  If it is #2, we don't.  Pass back shouldWarn to let the caller know.
        private IList <GeometryObject> CreateGeometryFromMaterialLayerUsage(IFCImportShapeEditScope shapeEditScope, Transform extrusionPosition,
                                                                            IList <CurveLoop> loops, XYZ extrusionDirection, double currDepth, out ElementId materialId, out bool shouldWarn)
        {
            IList <GeometryObject> extrusionSolids = null;

            materialId = ElementId.InvalidElementId;

            try
            {
                shouldWarn = true; // Invalid input.

                // Check for valid input.
                if (shapeEditScope == null ||
                    extrusionPosition == null ||
                    loops == null ||
                    loops.Count() == 0 ||
                    extrusionDirection == null ||
                    !extrusionPosition.IsConformal ||
                    !Application.IsValidThickness(currDepth))
                {
                    return(null);
                }

                IFCProduct creator = shapeEditScope.Creator;
                if (creator == null)
                {
                    return(null);
                }

                shouldWarn = false; // Missing, empty, or optimized out IfcMaterialLayerSetUsage - valid reason to stop.

                IIFCMaterialSelect materialSelect = creator.MaterialSelect;
                if (materialSelect == null)
                {
                    return(null);
                }

                IFCMaterialLayerSetUsage materialLayerSetUsage = materialSelect as IFCMaterialLayerSetUsage;
                if (materialLayerSetUsage == null)
                {
                    return(null);
                }

                IFCMaterialLayerSet materialLayerSet = materialLayerSetUsage.MaterialLayerSet;
                if (materialLayerSet == null)
                {
                    return(null);
                }

                IList <IFCMaterialLayer> materialLayers = materialLayerSet.MaterialLayers;
                if (materialLayers == null || materialLayers.Count == 0)
                {
                    return(null);
                }

                // Optimization: if there is only one layer, use the standard method, with possibly an overloaded material.
                ElementId baseMaterialId = GetMaterialElementId(shapeEditScope);
                if (materialLayers.Count == 1)
                {
                    IFCMaterial oneMaterial = materialLayers[0].Material;
                    if (oneMaterial == null)
                    {
                        return(null);
                    }

                    materialId = oneMaterial.GetMaterialElementId();
                    if (materialId != ElementId.InvalidElementId)
                    {
                        // We will not override the material of the element if the layer material has no color.
                        if (Importer.TheCache.MaterialsWithNoColor.Contains(materialId))
                        {
                            materialId = ElementId.InvalidElementId;
                        }
                    }

                    return(null);
                }

                // Anything below here is something we should report to the user, with the exception of the total thickness
                // not matching the extrusion thickness.  This would require more analysis to determine that it is actually
                // an error condition.
                shouldWarn = true;

                IList <IFCMaterialLayer> realMaterialLayers = new List <IFCMaterialLayer>();
                double totalThickness = 0.0;
                foreach (IFCMaterialLayer materialLayer in materialLayers)
                {
                    double depth = materialLayer.LayerThickness;
                    if (MathUtil.IsAlmostZero(depth))
                    {
                        continue;
                    }

                    if (depth < 0.0)
                    {
                        return(null);
                    }

                    realMaterialLayers.Add(materialLayer);
                    totalThickness += depth;
                }

                // Axis3 means that the material layers are stacked in the Z direction.  This is common for floor slabs.
                bool isAxis3 = (materialLayerSetUsage.Direction == IFCLayerSetDirection.Axis3);

                // For elements extruded in the Z direction, if the extrusion layers don't have the same thickness as the extrusion,
                // this could be one of two reasons:
                // 1. There is a discrepancy between the extrusion depth and the material layer set usage calculated depth.
                // 2. There are multiple extrusions in the body definition.
                // In either case, we will use the extrusion geometry over the calculated material layer set usage geometry.
                // In the future, we may decide to allow for case #1 by passing in a flag to allow for this.
                if (isAxis3 && !MathUtil.IsAlmostEqual(totalThickness, currDepth))
                {
                    shouldWarn = false;
                    return(null);
                }

                int numLayers = realMaterialLayers.Count();
                if (numLayers == 0)
                {
                    return(null);
                }
                // We'll use this initial value for the Axis2 case, so read it here.
                double baseOffsetForLayer = materialLayerSetUsage.Offset;

                // Needed for Axis2 case only.  The axisCurve is the curve defined in the product representation representing
                // a base curve (an axis) for the footprint of the element.
                Curve axisCurve = null;

                // The oriented cuve list represents the 4 curves of supported Axis2 footprint in the following order:
                // 1. curve along length of object closest to the first material layer with the orientation of the axis curve
                // 2. connecting end curve
                // 3. curve along length of object closest to the last material layer with the orientation opposite of the axis curve
                // 4. connecting end curve.
                IList <Curve> orientedCurveList = null;

                if (!isAxis3)
                {
                    // Axis2 means that the material layers are stacked inthe Y direction.  This is by definition for IfcWallStandardCase,
                    // which has a local coordinate system whose Y direction is orthogonal to the length of the wall.
                    if (materialLayerSetUsage.Direction == IFCLayerSetDirection.Axis2)
                    {
                        axisCurve = GetAxisCurve(creator, extrusionPosition);
                        if (axisCurve == null)
                        {
                            return(null);
                        }

                        orientedCurveList = GetOrientedCurveList(loops, axisCurve, extrusionPosition.BasisZ, baseOffsetForLayer, totalThickness);
                        if (orientedCurveList == null)
                        {
                            return(null);
                        }
                    }
                    else
                    {
                        return(null); // Not handled.
                    }
                }

                extrusionSolids = new List <GeometryObject>();

                bool positiveOrientation = (materialLayerSetUsage.DirectionSense == IFCDirectionSense.Positive);

                // Always extrude in the positive direction for Axis2.
                XYZ materialExtrusionDirection = (positiveOrientation || !isAxis3) ? extrusionDirection : -extrusionDirection;

                // Axis2 repeated values.
                // The IFC concept of offset direction is reversed from Revit's.
                XYZ    normalDirectionForAxis2 = positiveOrientation ? -extrusionPosition.BasisZ : extrusionPosition.BasisZ;
                bool   axisIsCyclic            = (axisCurve == null) ? false : axisCurve.IsCyclic;
                double axisCurvePeriod         = axisIsCyclic ? axisCurve.Period : 0.0;

                Transform curveLoopTransform = Transform.Identity;

                IList <CurveLoop> currLoops  = null;
                double            depthSoFar = 0.0;

                for (int ii = 0; ii < numLayers; ii++)
                {
                    IFCMaterialLayer materialLayer = materialLayers[ii];

                    // Ignore 0 thickness layers.  No need to warn.
                    double depth = materialLayer.LayerThickness;
                    if (MathUtil.IsAlmostZero(depth))
                    {
                        continue;
                    }

                    // If the thickness is non-zero but invalid, fail.
                    if (!Application.IsValidThickness(depth))
                    {
                        return(null);
                    }

                    double extrusionDistance = 0.0;
                    if (isAxis3)
                    {
                        // Offset the curve loops if necessary, using the base extrusionDirection, regardless of the direction sense
                        // of the MaterialLayerSetUsage.
                        double offsetForLayer = positiveOrientation ? baseOffsetForLayer + depthSoFar : baseOffsetForLayer - depthSoFar;
                        if (!MathUtil.IsAlmostZero(offsetForLayer))
                        {
                            curveLoopTransform.Origin = offsetForLayer * extrusionDirection;

                            currLoops = new List <CurveLoop>();
                            foreach (CurveLoop loop in loops)
                            {
                                CurveLoop newLoop = CurveLoop.CreateViaTransform(loop, curveLoopTransform);
                                if (newLoop == null)
                                {
                                    return(null);
                                }

                                currLoops.Add(newLoop);
                            }
                        }
                        else
                        {
                            currLoops = loops;
                        }

                        extrusionDistance = depth;
                    }
                    else
                    {
                        // startClipCurve, firstEndCapCurve, endClipCurve, secondEndCapCurve.
                        Curve[]    outline       = new Curve[4];
                        double[][] endParameters = new double[4][];

                        double startClip = depthSoFar;
                        double endClip   = depthSoFar + depth;

                        outline[0] = orientedCurveList[0].CreateOffset(startClip, normalDirectionForAxis2);
                        outline[1] = orientedCurveList[1].Clone();
                        outline[2] = orientedCurveList[2].CreateOffset(totalThickness - endClip, normalDirectionForAxis2);
                        outline[3] = orientedCurveList[3].Clone();

                        for (int jj = 0; jj < 4; jj++)
                        {
                            outline[jj].MakeUnbound();
                            endParameters[jj]    = new double[2];
                            endParameters[jj][0] = 0.0;
                            endParameters[jj][1] = 0.0;
                        }

                        // Trim/Extend the curves so that they make a closed loop.
                        for (int jj = 0; jj < 4; jj++)
                        {
                            IntersectionResultArray resultArray = null;
                            outline[jj].Intersect(outline[(jj + 1) % 4], out resultArray);
                            if (resultArray == null || resultArray.Size == 0)
                            {
                                return(null);
                            }

                            int numResults = resultArray.Size;
                            if ((numResults > 1 && !axisIsCyclic) || (numResults > 2))
                            {
                                return(null);
                            }

                            UV intersectionPoint = resultArray.get_Item(0).UVPoint;
                            endParameters[jj][1]           = intersectionPoint.U;
                            endParameters[(jj + 1) % 4][0] = intersectionPoint.V;

                            if (numResults == 2)
                            {
                                // If the current result is closer to the end of the curve, keep it.
                                UV newIntersectionPoint = resultArray.get_Item(1).UVPoint;

                                int    endParamIndex   = (jj % 2);
                                double newParamToCheck = newIntersectionPoint[endParamIndex];
                                double oldParamToCheck = (endParamIndex == 0) ? endParameters[jj][1] : endParameters[(jj + 1) % 4][0];
                                double currentEndPoint = (endParamIndex == 0) ?
                                                         orientedCurveList[jj].GetEndParameter(1) : orientedCurveList[(jj + 1) % 4].GetEndParameter(0);

                                // Put in range of [-Period/2, Period/2].
                                double newDist = (currentEndPoint - newParamToCheck) % axisCurvePeriod;
                                if (newDist < -axisCurvePeriod / 2.0)
                                {
                                    newDist += axisCurvePeriod;
                                }
                                if (newDist > axisCurvePeriod / 2.0)
                                {
                                    newDist -= axisCurvePeriod;
                                }

                                double oldDist = (currentEndPoint - oldParamToCheck) % axisCurvePeriod;
                                if (oldDist < -axisCurvePeriod / 2.0)
                                {
                                    oldDist += axisCurvePeriod;
                                }
                                if (oldDist > axisCurvePeriod / 2.0)
                                {
                                    oldDist -= axisCurvePeriod;
                                }

                                if (Math.Abs(newDist) < Math.Abs(oldDist))
                                {
                                    endParameters[jj][1]           = newIntersectionPoint.U;
                                    endParameters[(jj + 1) % 4][0] = newIntersectionPoint.V;
                                }
                            }
                        }

                        CurveLoop newCurveLoop = new CurveLoop();
                        for (int jj = 0; jj < 4; jj++)
                        {
                            if (endParameters[jj][1] < endParameters[jj][0])
                            {
                                if (!outline[jj].IsCyclic)
                                {
                                    return(null);
                                }
                                endParameters[jj][1] += Math.Floor(endParameters[jj][0] / axisCurvePeriod + 1.0) * axisCurvePeriod;
                            }

                            outline[jj].MakeBound(endParameters[jj][0], endParameters[jj][1]);
                            newCurveLoop.Append(outline[jj]);
                        }

                        currLoops = new List <CurveLoop>();
                        currLoops.Add(newCurveLoop);

                        extrusionDistance = currDepth;
                    }

                    // Determine the material id.
                    IFCMaterial material        = materialLayer.Material;
                    ElementId   layerMaterialId = (material == null) ? ElementId.InvalidElementId : material.GetMaterialElementId();

                    // The second option here is really for Referencing.  Without a UI (yet) to determine whether to show the base
                    // extusion or the layers for objects with material layer sets, we've chosen to display the base material if the layer material
                    // has no color information.  This means that the layer is assigned the "wrong" material, but looks better on screen.
                    // We will reexamine this decision (1) for the Open case, (2) if there is UI to toggle between layers and base extrusion, or
                    // (3) based on user feedback.
                    if (layerMaterialId == ElementId.InvalidElementId || Importer.TheCache.MaterialsWithNoColor.Contains(layerMaterialId))
                    {
                        layerMaterialId = baseMaterialId;
                    }

                    SolidOptions solidOptions = new SolidOptions(layerMaterialId, shapeEditScope.GraphicsStyleId);

                    // Create the extrusion for the material layer.
                    GeometryObject extrusionSolid = GeometryCreationUtilities.CreateExtrusionGeometry(
                        currLoops, materialExtrusionDirection, extrusionDistance, solidOptions);
                    if (extrusionSolid == null)
                    {
                        return(null);
                    }

                    extrusionSolids.Add(extrusionSolid);
                    depthSoFar += depth;
                }
            }
            catch
            {
                // Ignore the specific exception, but let the user know there was a problem processing the IfcMaterialLayerSetUsage.
                shouldWarn = true;
                return(null);
            }

            return(extrusionSolids);
        }
예제 #33
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            IFCAnyHandle points = IFCAnyHandleUtil.GetInstanceAttribute(ifcCurve, "Points");

            if (IFCAnyHandleUtil.IsNullOrHasNoValue(points))
            {
                Importer.TheLog.LogMissingRequiredAttributeError(ifcCurve, "Points", true);
                return;
            }

            IList <IFCData> segments = null;

            try
            {
                // The Segments attribute is new to IFC4 Add1, and we don't know that we may have a
                // vanilla IFC4 file.  If we can't find the attribute, we will assume the points represent
                // the vertices of a polyline.
                segments = IFCAnyHandleUtil.GetAggregateAttribute <List <IFCData> >(ifcCurve, "Segments");
            }
            catch (Exception ex)
            {
                if (IFCImportFile.HasUndefinedAttribute(ex))
                {
                    IFCImportFile.TheFile.DowngradeIFC4SchemaTo(IFCSchemaVersion.IFC4);
                }
                else
                {
                    throw ex;
                }
            }

            IFCCartesianPointList pointList     = IFCCartesianPointList.ProcessIFCCartesianPointList(points);
            IList <XYZ>           pointListXYZs = pointList.CoordList;
            int numPoints = pointListXYZs.Count;

            CurveLoop   curveLoop = null;
            IList <XYZ> pointXYZs = null;

            if (segments == null)
            {
                // Simple case: no segment information, just treat the curve as a polyline.
                pointXYZs = pointListXYZs;
                curveLoop = IFCGeometryUtil.CreatePolyCurveLoop(pointXYZs, null, Id, false);
            }
            else
            {
                curveLoop = new CurveLoop();

                // Assure that we don't add the same point twice for a polyline segment.  This could
                // happen by error, or, e.g., there are two IfcLineIndex segments in a row (although
                // this could also be considered an error condition.)
                int lastIndex = -1;

                // The list of all of the points, in the order that they are added.  This can be
                // used as a backup representation.
                pointXYZs = new List <XYZ>();

                IList <XYZ> currentLineSegmentPoints = new List <XYZ>();
                foreach (IFCData segment in segments)
                {
                    string indexType = ValidateSegment(segment);
                    if (indexType == null)
                    {
                        Importer.TheLog.LogError(Id, "Unknown segment type in IfcIndexedPolyCurve.", false);
                        continue;
                    }

                    IFCAggregate segmentInfo = segment.AsAggregate();

                    if (indexType.Equals("IfcLineIndex", StringComparison.OrdinalIgnoreCase))
                    {
                        foreach (IFCData segmentInfoIndex in segmentInfo)
                        {
                            int?currentIndex = GetValidIndex(segmentInfoIndex, numPoints);
                            if (currentIndex == null)
                            {
                                continue;
                            }

                            // We want to aggregate line segments, but if we have no points
                            // yet, we need to always add the start point.
                            int validCurrentIndex = currentIndex.Value;
                            if (lastIndex != validCurrentIndex || currentLineSegmentPoints.Count == 0)
                            {
                                XYZ currPt = pointListXYZs[validCurrentIndex];
                                pointXYZs.Add(currPt);
                                currentLineSegmentPoints.Add(currPt);
                                lastIndex = validCurrentIndex;
                            }
                        }
                    }
                    else if (indexType.Equals("IfcArcIndex", StringComparison.OrdinalIgnoreCase))
                    {
                        // Create any line segments that haven't been already created.
                        CreateLineSegments(curveLoop, currentLineSegmentPoints);

                        if (segmentInfo.Count != 3)
                        {
                            Importer.TheLog.LogError(Id, "Invalid IfcArcIndex in IfcIndexedPolyCurve.", false);
                            continue;
                        }

                        int?startIndex = GetValidIndex(segmentInfo[0], numPoints);
                        int?pointIndex = GetValidIndex(segmentInfo[1], numPoints);
                        int?endIndex   = GetValidIndex(segmentInfo[2], numPoints);

                        if (startIndex == null || pointIndex == null || endIndex == null)
                        {
                            continue;
                        }

                        Arc arcSegment = null;
                        XYZ startPoint = pointListXYZs[startIndex.Value];
                        XYZ pointOnArc = pointListXYZs[pointIndex.Value];
                        XYZ endPoint   = pointListXYZs[endIndex.Value];
                        try
                        {
                            arcSegment = Arc.Create(startPoint, endPoint, pointOnArc);
                            if (arcSegment != null)
                            {
                                curveLoop.Append(arcSegment);
                            }
                        }
                        catch
                        {
                            // We won't do anything here; it may be that the arc is very small, and can
                            // be repaired as a gap in the curve loop.  If it can't, this will fail later.
                            // We will monitor usage to see if anything more needs to be done here.
                        }

                        if (lastIndex != startIndex.Value)
                        {
                            pointXYZs.Add(startPoint);
                        }
                        pointXYZs.Add(pointOnArc);
                        pointXYZs.Add(endPoint);
                        lastIndex = endIndex.Value;
                    }
                    else
                    {
                        Importer.TheLog.LogError(Id, "Unsupported segment type in IfcIndexedPolyCurve.", false);
                        continue;
                    }
                }

                // Create any line segments that haven't been already created.
                CreateLineSegments(curveLoop, currentLineSegmentPoints);
            }

            SetCurveLoop(curveLoop, pointXYZs);
        }
예제 #34
0
 /// <summary>
 /// Adds a new opening to extrusion creation data from curve loop and extrusion data.
 /// </summary>
 /// <param name="creationData">The extrusion creation data.</param>
 /// <param name="from">The extrusion data.</param>
 /// <param name="curveLoop">The curve loop.</param>
 private static void AddOpeningData(IFCExtrusionCreationData creationData, IFCExtrusionData from, CurveLoop curveLoop)
 {
     List<CurveLoop> curveLoops = new List<CurveLoop>();
     curveLoops.Add(curveLoop);
     AddOpeningData(creationData, from, curveLoops);
 }
예제 #35
0
        /// <summary>
        /// Adds a new retaining pond.
        /// </summary>
        /// <param name="uiDoc">The document.</param>
        /// <param name="pondRadius">The radius of the pond.</param>
        private void AddNewRetainingPond(UIDocument uiDoc, double pondRadius)
        {
            Document doc = uiDoc.Document;

            // Find toposurfaces
            FilteredElementCollector tsCollector = new FilteredElementCollector(doc);

            tsCollector.OfClass(typeof(TopographySurface));
            IEnumerable <TopographySurface> tsEnumerable = tsCollector.Cast <TopographySurface>().Where <TopographySurface>(ts => !ts.IsSiteSubRegion);
            int count = tsEnumerable.Count <TopographySurface>();

            // If there is only on surface, use it.  If there is more than one, let the user select the target.
            TopographySurface targetSurface = null;

            if (count > 1) // tmp
            {
                targetSurface = SiteUIUtils.PickTopographySurface(uiDoc);
            }
            else
            {
                targetSurface = tsEnumerable.First <TopographySurface>();
            }

            // Pick point and project to plane at toposurface average elevation
            XYZ    point     = SiteUIUtils.PickPointNearToposurface(uiDoc, targetSurface, "Pick point for center of pond.");
            double elevation = point.Z;

            // Add subregion first, so that any previously existing points can be removed to avoid distorting the new region

            // Find material "Water"
            FilteredElementCollector collector = new FilteredElementCollector(doc);

            collector.OfClass(typeof(Material));
            Material mat = collector.Cast <Material>().FirstOrDefault <Material>(m => m.Name == "Water");

            // Create subregion curves
            List <Curve> curves = new List <Curve>();

            curves.Add(Arc.Create(point, pondRadius, 0, Math.PI, XYZ.BasisX, XYZ.BasisY));
            curves.Add(Arc.Create(point, pondRadius, Math.PI, 2 * Math.PI, XYZ.BasisX, XYZ.BasisY));

            CurveLoop        curveLoop  = CurveLoop.Create(curves);
            List <CurveLoop> curveLoops = new List <CurveLoop>();

            curveLoops.Add(curveLoop);

            // All changes are added to one transaction group - will create one undo item
            using (TransactionGroup addGroup = new TransactionGroup(doc, "Add pond group"))
            {
                addGroup.Start();

                IList <XYZ> existingPoints = null;
                // Transacton for adding subregion.
                using (Transaction t2 = new Transaction(doc, "Add subregion"))
                {
                    t2.Start();
                    SiteSubRegion region = SiteSubRegion.Create(doc, curveLoops, targetSurface.Id);
                    if (mat != null)
                    {
                        region.TopographySurface.MaterialId = mat.Id;
                    }
                    t2.Commit();

                    // The boundary points for the subregion cannot be deleted, since they are generated
                    // to represent the subregion boundary rather than representing real points in the host.
                    // Get non-boundary points only to be deleted.
                    existingPoints = SiteEditingUtils.GetNonBoundaryPoints(region.TopographySurface);

                    // Average elevation of all points in the subregion to use as base elevation for the pond topography
                    elevation = SiteEditingUtils.GetAverageElevation(region.TopographySurface.GetPoints());
                }

                // Add the topography points to the target surface via edit scope.
                using (TopographyEditScope editScope = new TopographyEditScope(doc, "Edit TS"))
                {
                    editScope.Start(targetSurface.Id);

                    // Transaction for points changes
                    using (Transaction t = new Transaction(doc, "Add points"))
                    {
                        t.Start();

                        // Delete existing points first to avoid conflict
                        if (existingPoints.Count > 0)
                        {
                            targetSurface.DeletePoints(existingPoints);
                        }

                        // Generate list of points to add
                        IList <XYZ> points = SiteEditingUtils.GeneratePondPointsSurrounding(new XYZ(point.X, point.Y, elevation - 3), pondRadius);
                        targetSurface.AddPoints(points);
                        t.Commit();
                    }

                    editScope.Commit(new TopographyEditFailuresPreprocessor());
                }
                addGroup.Assimilate();
            }
        }
예제 #36
0
        private GeometryObject CreateGeometryFromMaterialProfile(IFCImportShapeEditScope shapeEditScope,
                                                                 IList <CurveLoop> loops, XYZ extrusionDirection, double currDepth, SolidOptions solidOptions, out bool shouldWarn)
        {
            GeometryObject extrusionSolid = null;

            try
            {
                shouldWarn = true; // invalid input

                IIFCMaterialSelect materialSelect = shapeEditScope.Creator.MaterialSelect;
                if (materialSelect == null)
                {
                    return(null);
                }

                IFCMaterialProfileSetUsage matProfSetUsage = materialSelect as IFCMaterialProfileSetUsage;
                if (matProfSetUsage == null)
                {
                    return(null);
                }

                IFCMaterialProfileSet matProfSet = matProfSetUsage.ForProfileSet;
                if (matProfSet == null)
                {
                    return(null);
                }

                IList <IFCMaterialProfile> matProfList = matProfSet.MaterialProfileSet;
                if (matProfList.Count == 0)
                {
                    return(null);
                }

                Transform         transformByOffset = Transform.Identity;
                IList <CurveLoop> newloops          = new List <CurveLoop>();

                ElementId materialId = null;
                foreach (IFCMaterialProfile matProf in matProfList)
                {
                    if (this.SweptArea.Id == matProf.Profile.Id)
                    {
                        // This is the same id (same profile), use the material name for creation of this geometry
                        IFCMaterial theMaterial = matProf.Material;
                        if (theMaterial != null)
                        {
                            materialId = theMaterial.GetMaterialElementId();
                            solidOptions.MaterialId = materialId; // Override the original option if the profile has a specific material id
                        }

                        // Here we will handle special case if the Material Profile has Offset
                        if (matProf is IFCMaterialProfileWithOffsets)
                        {
                            IFCMaterialProfileWithOffsets matProfOffset = matProf as IFCMaterialProfileWithOffsets;
                            double startOffset = matProfOffset.OffsetValues[0];
                            double endOffset   = 0;
                            if (matProfOffset.OffsetValues.Count > 1)
                            {
                                endOffset = matProfOffset.OffsetValues[1];
                            }

                            // To handle offset, we need to move the start point (extrusion position) to the startOffset value along the axis (extrusion direction)
                            // For the end offset, we will have to re-calculate the extrusion
                            currDepth = currDepth - startOffset + endOffset;
                            transformByOffset.Origin += startOffset * extrusionDirection;
                            foreach (CurveLoop loop in loops)
                            {
                                CurveLoop newLoop = CurveLoop.CreateViaTransform(loop, transformByOffset);
                                newloops.Add(newLoop);
                            }
                        }
                        break;
                    }
                }

                if (newloops.Count == 0)
                {
                    extrusionSolid = GeometryCreationUtilities.CreateExtrusionGeometry(loops, extrusionDirection, currDepth, solidOptions);
                }
                else
                {
                    extrusionSolid = GeometryCreationUtilities.CreateExtrusionGeometry(newloops, extrusionDirection, currDepth, solidOptions);
                }
            }
            catch
            {
                // Ignore the specific exception, but let the user know there was a problem processing the IfcMaterialLayerSetUsage.
                shouldWarn = true;
                return(null);
            }

            return(extrusionSolid);
        }
예제 #37
0
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry, without scale.</param>
        /// <param name="scaledLcs">Local coordinate system for the geometry, including scale, potentially non-uniform.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>Zero or more created geometries.</returns>
        protected override IList<GeometryObject> CreateGeometryInternal(
              IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            Transform sweptDiskPosition = (lcs == null) ? Transform.Identity : lcs;

            CurveLoop baseProfileCurve = Directrix.GetCurveLoop();
            if (baseProfileCurve == null)
                return null;

            CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(baseProfileCurve, StartParameter, EndParameter);
            if (trimmedDirectrix == null)
                return null;

            CurveLoop trimmedDirectrixInLCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, sweptDiskPosition);

            // Create the disk.
            Transform originTrf = null;
            double startParam = 0.0; // If the directrix isn't bound, this arbitrary parameter will do.
            foreach (Curve curve in trimmedDirectrixInLCS)
            {
                if (curve.IsBound)
                    startParam = curve.GetEndParameter(0);
                originTrf = curve.ComputeDerivatives(startParam, false);
                break;
            }

            if (originTrf == null)
                return null;

            // The X-dir of the transform of the start of the directrix will form the normal of the disk.
            Plane diskPlane = new Plane(originTrf.BasisX, originTrf.Origin);

            IList<CurveLoop> profileCurveLoops = new List<CurveLoop>();

            CurveLoop diskOuterCurveLoop = new CurveLoop();
            diskOuterCurveLoop.Append(Arc.Create(diskPlane, Radius, 0, Math.PI));
            diskOuterCurveLoop.Append(Arc.Create(diskPlane, Radius, Math.PI, 2.0 * Math.PI));
            profileCurveLoops.Add(diskOuterCurveLoop);
            
            if (InnerRadius.HasValue)
            {
                CurveLoop diskInnerCurveLoop = new CurveLoop();
                diskInnerCurveLoop.Append(Arc.Create(diskPlane, InnerRadius.Value, 0, Math.PI));
                diskInnerCurveLoop.Append(Arc.Create(diskPlane, InnerRadius.Value, Math.PI, 2.0 * Math.PI));
                profileCurveLoops.Add(diskInnerCurveLoop);
            }

            SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInLCS, 0, startParam, profileCurveLoops,
                solidOptions);

            IList<GeometryObject> myObjs = new List<GeometryObject>();
            if (sweptDiskSolid != null)
                myObjs.Add(sweptDiskSolid);
            return myObjs;
        }
예제 #38
0
        void CommitInstance
        (
            Document doc, IGH_DataAccess DA, int Iteration,
            IEnumerable <Rhino.Geometry.Point3d> points,
            IEnumerable <Rhino.Geometry.Curve> regions
        )
        {
            var element = PreviousElement(doc, Iteration);

            if (!element?.Pinned ?? false)
            {
                ReplaceElement(doc, DA, Iteration, element);
            }
            else
            {
                try
                {
                    var scaleFactor = 1.0 / Revit.ModelUnits;
                    if (scaleFactor != 1.0)
                    {
                        points = points.Select(p => p * scaleFactor);

                        foreach (var region in regions)
                        {
                            region.Scale(scaleFactor);
                        }
                    }

                    TopographySurface topography = null;
                    //if (element is TopographySurface topography)
                    //{
                    //  using (var editScope = new TopographyEditScope(doc, "TopographyByPoints"))
                    //  {
                    //    editScope.Start(element.Id);
                    //    topography.DeletePoints(topography.GetPoints());
                    //    topography.AddPoints(points.ToHost().ToList());

                    //    foreach (var subRegionId in topography.GetHostedSubRegionIds())
                    //      doc.Delete(subRegionId);

                    //    editScope.Commit(new Revit.FailuresPreprocessor());
                    //  }
                    //}
                    //else
                    {
                        topography = CopyParametersFrom(TopographySurface.Create(doc, points.ToHost().ToList()), element);
                        element    = topography;
                    }

                    if (topography != null && regions.Any())
                    {
                        var curveLoops = regions.Select(region => CurveLoop.Create(region.ToHost().ToList())).ToList();
                        SiteSubRegion.Create(doc, curveLoops, topography.Id);
                    }

                    ReplaceElement(doc, DA, Iteration, element);
                }
                catch (Exception e)
                {
                    AddRuntimeMessage(GH_RuntimeMessageLevel.Error, e.Message);
                    ReplaceElement(doc, DA, Iteration, null);
                }
            }
        }
      protected override void Process(IFCAnyHandle ifcCurve)
      {
         base.Process(ifcCurve);

         // We are going to attempt minor repairs for small but reasonable gaps between Line/Line and Line/Arc pairs.  As such, we want to collect the
         // curves before we create the curve loop.

         IList<IFCAnyHandle> segments = IFCAnyHandleUtil.GetAggregateInstanceAttribute<List<IFCAnyHandle>>(ifcCurve, "Segments");
         if (segments == null)
            Importer.TheLog.LogError(Id, "Invalid IfcCompositeCurve with no segments.", true);

         // need List<> so that we can AddRange later.
         List<Curve> curveSegments = new List<Curve>();
         foreach (IFCAnyHandle segment in segments)
         {
            IList<Curve> currCurve = ProcessIFCCompositeCurveSegment(segment);
            if (currCurve != null && currCurve.Count != 0)
               curveSegments.AddRange(currCurve);
         }

         int numSegments = curveSegments.Count;
         if (numSegments == 0)
            Importer.TheLog.LogError(Id, "Invalid IfcCompositeCurve with no segments.", true);

         try
         {
            // We are going to try to reverse or tweak segments as necessary to make the CurveLoop.
            // For each curve, it is acceptable if it can be appended to the end of the existing loop, or prepended to its start, 
            // possibly after reversing the curve, and possibly with some tweaking.
            
            // NOTE: we do not do any checks yet to repair the endpoints of the curveloop to make them closed.
            // NOTE: this is not expected to be perfect with dirty data, but is expected to not change already valid data.

            // curveLoopStartPoint and curveLoopEndPoint will change over time as we add new curves to the start or end of the CurveLoop.
            XYZ curveLoopStartPoint = curveSegments[0].GetEndPoint(0);
            XYZ curveLoopEndPoint = curveSegments[0].GetEndPoint(1);

            double vertexEps = IFCImportFile.TheFile.Document.Application.VertexTolerance;

            // This is intended to be "relatively large".  The idea here is that the user would rather have the information presented
            // than thrown away because of a gap that is architecturally insignificant.
            double gapVertexEps = Math.Max(vertexEps, 0.01); // 1/100th of a foot, or 3.048 mm.
            double shortCurveTol = IFCImportFile.TheFile.Document.Application.ShortCurveTolerance;

            // canRepairFirst may change over time, as we may potentially add curves to the start of the CurveLoop.
            bool canRepairFirst = (curveSegments[0] is Line);
            for (int ii = 1; ii < numSegments; ii++)
            {
               XYZ nextStartPoint = curveSegments[ii].GetEndPoint(0);
               XYZ nextEndPoint = curveSegments[ii].GetEndPoint(1);

               // These will be set below.
               bool attachNextSegmentToEnd = false;
               bool reverseNextSegment = false;
               double minGap = 0.0;

               // Scoped to prevent distLoopEndPtToNextStartPt and others from being used later on.
               {
                  // Find the minimum gap between the current curve segment and the existing curve loop.  If it is too large, we will give up.
                  double distLoopEndPtToNextStartPt = curveLoopEndPoint.DistanceTo(nextStartPoint);
                  double distLoopEndPtToNextEndPt = curveLoopEndPoint.DistanceTo(nextEndPoint);

                  double distLoopStartPtToNextEndPt = curveLoopStartPoint.DistanceTo(nextEndPoint);
                  double distLoopStartPtToNextStartPt = curveLoopStartPoint.DistanceTo(nextStartPoint);

                  // Determine the minimum gap between the two curves.  If it is too large, we'll give up before trying anything.
                  double minStartGap = Math.Min(distLoopStartPtToNextEndPt, distLoopStartPtToNextStartPt);
                  double minEndGap = Math.Min(distLoopEndPtToNextStartPt, distLoopEndPtToNextEndPt);
                  
                  minGap = Math.Min(minStartGap, minEndGap);

                  // If the minimum distance between the two curves is greater than gapVertexEps (which is the larger of our two tolerances), 
                  // we can't fix the issue.
                  if (minGap > gapVertexEps)
                  {
                     string lengthAsString = UnitFormatUtils.Format(IFCImportFile.TheFile.Document.GetUnits(), UnitType.UT_Length, minGap, true, false);
                     string maxGapAsString = UnitFormatUtils.Format(IFCImportFile.TheFile.Document.GetUnits(), UnitType.UT_Length, gapVertexEps, true, false);
                     throw new InvalidOperationException("IfcCompositeCurve contains a gap of " + lengthAsString +
                        " that is greater than the maximum gap size of " + maxGapAsString +
                        " and cannot be repaired.");
                  }

                  // We have a possibility to add the segment.  What we do depends on the gap distance.

                  // If the current curve loop's closest end to the next segment is its end (vs. start) point, set attachNextSegmentToEnd to true.
                  attachNextSegmentToEnd = (MathUtil.IsAlmostEqual(distLoopEndPtToNextStartPt, minGap)) ||
                     (MathUtil.IsAlmostEqual(distLoopEndPtToNextEndPt, minGap));

                  // We need to reverse the next segment if:
                  // 1. We are attaching the next segment to the end of the curve loop, and the next segment's closest end to the current curve loop is its end (vs. start) point.
                  // 2. We are attaching the next segment to the start of the curve loop, and the next segment's closest end to the current curve loop is its start (vs. end) point.
                  reverseNextSegment = (MathUtil.IsAlmostEqual(distLoopEndPtToNextEndPt, minGap)) ||
                     (MathUtil.IsAlmostEqual(distLoopStartPtToNextStartPt, minGap));
               }

               if (reverseNextSegment)
               {
                  curveSegments[ii] = curveSegments[ii].CreateReversed();
                  MathUtil.Swap<XYZ>(ref nextStartPoint, ref nextEndPoint);
               }

               // If minGap is less than vertexEps, we won't need to do any repairing - just fix the orientation if necessary.
               if (minGap < vertexEps)
               {
                  if (attachNextSegmentToEnd)
                  {
                     // Update the curve loop end point to be the end point of the next segment after potentially being reversed.
                     curveLoopEndPoint = nextEndPoint;
                  }
                  else
                  {
                     canRepairFirst = curveSegments[ii] is Line;
                     curveLoopStartPoint = nextStartPoint;

                     // Update the curve loop start point to be the start point of the next segment, now at the beginning of the loop,
                     // after potentially being reversed.
                     Curve tmpCurve = curveSegments[ii];
                     curveSegments.RemoveAt(ii);
                     curveSegments.Insert(0, tmpCurve);
                  }

                  continue;
               }

               // The gap is too big for CurveLoop, but smaller than our maximum tolerance - we will try to fix the gap by extending
               // one of the line segments around the gap.  If the gap is between two Arcs, we will try to introduce a short
               // segment between them, as long as the gap is larger than the short curve tolerance.

               bool canRepairNext = curveSegments[ii] is Line;
               bool createdRepairLine = false;

               if (attachNextSegmentToEnd)
               {
                  // Update the curve loop end point to be the end point of the next segment after potentially being reversed.
                  XYZ originalCurveLoopEndPoint = curveLoopEndPoint;
                  curveLoopEndPoint = nextEndPoint;
                  if (canRepairNext)
                     curveSegments[ii] = RepairLineAndReport(Id, originalCurveLoopEndPoint, curveLoopEndPoint, minGap);
                  else if (curveSegments[ii - 1] is Line)  // = canRepairCurrent, only used here.
                     curveSegments[ii - 1] = RepairLineAndReport(Id, curveSegments[ii - 1].GetEndPoint(0), curveSegments[ii].GetEndPoint(0), minGap);
                  else
                  {
                     // Can't add a line to fix a gap that is smaller than the short curve tolerance.
                     // In the future, we may fix this gap by intersecting the two curves and extending one of them.
                     if (minGap < shortCurveTol + MathUtil.Eps())
                        Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that is too short to be repaired by a connecting segment.", true);

                     try
                     {
                        Line repairLine = Line.CreateBound(originalCurveLoopEndPoint, curveSegments[ii].GetEndPoint(0));
                        curveSegments.Insert(ii, repairLine);
                        ii++; // Skip the repair line as we've already "added" it and the non-linear segment to our growing loop.
                        numSegments++;
                        createdRepairLine = true;
                     }
                     catch
                     {
                        Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that can't be fixed.", true);
                     }
                  }
               }
               else
               {
                  XYZ originalCurveLoopStartPoint = curveLoopStartPoint;
                  curveLoopStartPoint = nextStartPoint;

                  if (canRepairNext)
                  {
                     curveSegments[ii] = RepairLineAndReport(Id, curveLoopStartPoint, originalCurveLoopStartPoint, minGap);
                  }
                  else if (canRepairFirst)
                     curveSegments[0] = RepairLineAndReport(Id, curveSegments[ii].GetEndPoint(1), curveSegments[0].GetEndPoint(1), minGap);
                  else
                  {
                     // Can't add a line to fix a gap that is smaller than the short curve tolerance.
                     // In the future, we may fix this gap by intersecting the two curves and extending one of them.
                     if (minGap < shortCurveTol + MathUtil.Eps())
                        Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that is too short to be repaired by a connecting segment.", true);

                     Line repairLine = Line.CreateBound(curveSegments[ii].GetEndPoint(1), originalCurveLoopStartPoint);
                     curveSegments.Insert(0, repairLine);
                     ii++; // Skip the repair line as we've already "added" it and the non-linear curve to our growing loop.
                     numSegments++;
                  }

                  // Either canRepairFirst was already true, or canRepairNext was true and we added it to the front of the loop, 
                  // or we added a short repair line to the front of the loop.  In any of these cases, the front curve segement of the
                  // loop is now a line segment.
                  if (!canRepairFirst && !canRepairNext && !createdRepairLine)
                     Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that can't be fixed.", true);

                  canRepairFirst = true;

                  // Move the curve to the front of the loop.
                  Curve tmpCurve = curveSegments[ii];
                  curveSegments.RemoveAt(ii);
                  curveSegments.Insert(0, tmpCurve);
               }
            }

            if (CurveLoop == null)
               CurveLoop = new CurveLoop();

            foreach (Curve curveSegment in curveSegments)
            {
               CurveLoop.Append(curveSegment);
            }
         }
         catch (Exception ex)
         {
            Importer.TheLog.LogError(Id, ex.Message, true);
         }

         // Try to create the curve representation of this IfcCompositeCurve
         Curve = ConvertCurveLoopIntoSingleCurve(CurveLoop);
      }
예제 #40
0
        public static Solid CreateSolidByLoopExtrusion(this Face face, double distance = 0.1)
        {
            CurveLoop loop = face.GetEdgesAsCurveLoops().First();

            return(CreateSolidByLoopExtrusion(face.ComputeNormal(UV.Zero), loop, distance));
        }
예제 #41
0
        /// <summary>
        /// Computes height and width of a curve loop with respect to the projection plane.
        /// </summary>
        /// <param name="curveLoop">The curve loop.</param>
        /// <param name="plane">The projection plane.</param>
        /// <param name="height">The height.</param>
        /// <param name="width">The width.</param>
        /// <returns>True if success, false if fail.</returns>
        public static bool ComputeHeightWidthOfCurveLoop(CurveLoop curveLoop, Plane plane, out double height, out double width)
        {
            height = 0.0;
            width = 0.0;

            Plane localPlane = plane;
            if (localPlane == null)
            {
                try
                {
                    localPlane = curveLoop.GetPlane();
                }
                catch
                {
                    return false;
                }
            }

            if (curveLoop.IsRectangular(localPlane))
            {
                height = curveLoop.GetRectangularHeight(localPlane);
                width = curveLoop.GetRectangularWidth(localPlane);
                return true;
            }
            else
                return false;
        }
예제 #42
0
 public static Solid CreateSolidByLoopExtrusion(XYZ normal, CurveLoop loop, double distance = 0.1)
 {
     return(GeometryCreationUtilities.CreateExtrusionGeometry(new List <CurveLoop> {
         loop
     }, normal, distance));
 }
      protected override void Process(IFCAnyHandle ifcCurve)
      {
         base.Process(ifcCurve);

         bool found = false;

         bool sameSense = IFCImportHandleUtil.GetRequiredBooleanAttribute(ifcCurve, "SenseAgreement", out found);
         if (!found)
            sameSense = true;

         IFCAnyHandle basisCurve = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurve, "BasisCurve", true);
         IFCCurve ifcBasisCurve = IFCCurve.ProcessIFCCurve(basisCurve);
         if (ifcBasisCurve == null || (ifcBasisCurve.Curve == null && ifcBasisCurve.CurveLoop == null))
         {
            // LOG: ERROR: Error processing BasisCurve # for IfcTrimmedCurve #.
            return;
         }
         if (ifcBasisCurve.Curve == null)
         {
            // LOG: ERROR: Expected a single curve, not a curve loop for BasisCurve # for IfcTrimmedCurve #.
            return;
         }

         IFCData trim1 = ifcCurve.GetAttribute("Trim1");
         if (trim1.PrimitiveType != IFCDataPrimitiveType.Aggregate)
         {
            // LOG: ERROR: Invalid data type for Trim1 attribute for IfcTrimmedCurve #.
            return;
         }
         IFCData trim2 = ifcCurve.GetAttribute("Trim2");
         if (trim2.PrimitiveType != IFCDataPrimitiveType.Aggregate)
         {
            // LOG: ERROR: Invalid data type for Trim1 attribute for IfcTrimmedCurve #.
            return;
         }

         IFCTrimmingPreference trimPreference = IFCEnums.GetSafeEnumerationAttribute<IFCTrimmingPreference>(ifcCurve, "MasterRepresentation", IFCTrimmingPreference.Parameter);

         double param1 = 0.0, param2 = 0.0;
         try
         {
            GetTrimParameters(trim1, trim2, ifcBasisCurve, trimPreference, out param1, out param2);
         }
         catch (Exception ex)
         {
            Importer.TheLog.LogError(ifcCurve.StepId, ex.Message, false);
            return;
         }

         Curve baseCurve = ifcBasisCurve.Curve;
         if (baseCurve.IsCyclic)
         {
            if (!sameSense)
               MathUtil.Swap(ref param1, ref param2);

            if (param2 < param1)
               param2 = MathUtil.PutInRange(param2, param1 + Math.PI, 2 * Math.PI);

            if (param2 - param1 > 2.0 * Math.PI - MathUtil.Eps())
            {
               Importer.TheLog.LogWarning(ifcCurve.StepId, "IfcTrimmedCurve length is greater than 2*PI, leaving unbound.", false);
               Curve = baseCurve;
               return;
            }

            Curve = baseCurve.Clone();

            try
            {
               Curve.MakeBound(param1, param2);
            }
            catch (Exception ex)
            {
               if (ex.Message.Contains("too small"))
               {
                  Curve = null;
                  Importer.TheLog.LogError(Id, "curve length is invalid, ignoring.", false);
                  return;
               }
               else
                  throw ex;
            }
         }
         else
         {
            if (MathUtil.IsAlmostEqual(param1, param2))
            {
               Importer.TheLog.LogError(Id, "Param1 = Param2 for IfcTrimmedCurve #, ignoring.", false);
               return;
            }

            if (param1 > param2 - MathUtil.Eps())
            {
               Importer.TheLog.LogWarning(Id, "Param1 > Param2 for IfcTrimmedCurve #, reversing.", false);
               MathUtil.Swap(ref param1, ref param2);
               return;
            }

            Curve copyCurve = baseCurve.Clone();

            double length = param2 - param1;
            if (length <= IFCImportFile.TheFile.Document.Application.ShortCurveTolerance)
            {
               string lengthAsString = IFCUnitUtil.FormatLengthAsString(length);
               Importer.TheLog.LogError(Id, "curve length of " + lengthAsString + " is invalid, ignoring.", false);
               return;
            }

            copyCurve.MakeBound(param1, param2);
            if (sameSense)
            {
               Curve = copyCurve;
            }
            else
            {
               Curve = copyCurve.CreateReversed();
            }
         }

         CurveLoop = new CurveLoop();
         CurveLoop.Append(Curve);
      }
예제 #44
0
        /// <summary>ElementIntersectsSolidFilter: 找到与某Solid相交的Elements </summary>
        public void FindIntersectWallsByGeometry()
        {
            Transaction trans = new Transaction(Doc, "ExComm");

            trans.Start();

            // ---------------- 在API内存中创建一个拉伸Solid的定义(但是并不包含在Document中) ----------------
            //pick a point to draw solid
            Selection sel = UIDoc.Selection;
            XYZ       pt  = sel.PickPoint("Please pick a point to get the close walls");

            XYZ pttemp1 = sel.PickPoint(ObjectSnapTypes.None, "Pick leader end...");
            XYZ pttemp2 = sel.PickPoint(ObjectSnapTypes.None, "Pick leader elbow...");

            double dBoxLength = 3;
            // 创建进行拉伸的闭合曲线
            XYZ pt1 = new XYZ(pt.X - dBoxLength / 2, pt.Y - dBoxLength / 2, pt.Z);
            XYZ pt2 = new XYZ(pt.X + dBoxLength / 2, pt.Y - dBoxLength / 2, pt.Z);
            XYZ pt3 = new XYZ(pt.X + dBoxLength / 2, pt.Y + dBoxLength / 2, pt.Z);
            XYZ pt4 = new XYZ(pt.X - dBoxLength / 2, pt.Y + dBoxLength / 2, pt.Z);

            // 闭合曲线的四条边
            Line lineBottom = Line.CreateBound(pt1, pt2);
            Line lineRight  = Line.CreateBound(pt2, pt3);
            Line lineTop    = Line.CreateBound(pt3, pt4);
            Line lineLeft   = Line.CreateBound(pt4, pt1);

            // 将四条边连接起来
            CurveLoop profile = new CurveLoop();

            profile.Append(lineBottom);
            profile.Append(lineRight);
            profile.Append(lineTop);
            profile.Append(lineLeft);

            // 创建闭合的连续曲线段
            List <CurveLoop> loops = new List <CurveLoop>();

            loops.Add(profile);

            // 创建出一个Solid:此Solid只是为了与其他API交互,并未保存在Document中,所以也不可见。
            XYZ   vector = new XYZ(0, 0, 1);
            Solid solid  = GeometryCreationUtilities.CreateExtrusionGeometry(loops, vector, 10);

            // 在整个文档中搜索与此虚拟定义的Solid相交的Element
            FilteredElementCollector     collector   = new FilteredElementCollector(Doc);
            ElementIntersectsSolidFilter solidFilter = new ElementIntersectsSolidFilter(solid);

            collector.WherePasses(solidFilter);

            // 将最终的相交结果选中
            List <ElementId> selEle = new List <ElementId>();

            foreach (Element elem in collector)
            {
                selEle.Add(elem.Id);
            }
            sel.SetElementIds(selEle);
            //
            trans.Commit();
        }
예제 #45
0
        private static IList<CurveLoop> GetBoundaryLoopsFromBaseCurve(Wall wallElement, 
            IList<IList<IFCConnectedWallData>> connectedWalls,
            Curve baseCurve,
            Curve trimmedCurve,
            double unscaledWidth,
            double scaledDepth)
        {
            // If we don't have connected wall information, we can't clip them away.  Abort.
            if (connectedWalls == null)
                return null;

            Curve axisCurve = MaybeStretchBaseCurve(baseCurve, trimmedCurve);
            if (axisCurve == null)
                return null;

            // Create the extruded wall minus the wall joins.
            Solid baseSolid = CreateWallEndClippedWallGeometry(wallElement, connectedWalls, axisCurve, unscaledWidth, scaledDepth);
            if (baseSolid == null)
                return null;

            // Get the one face pointing in the -Z direction.  If there are multiple, abort.
            IList<CurveLoop> boundaryLoops = new List<CurveLoop>();
            foreach (Face potentialBaseFace in baseSolid.Faces)
            {
                if (potentialBaseFace is PlanarFace)
                {
                    PlanarFace planarFace = potentialBaseFace as PlanarFace;
                    if (planarFace.Normal.IsAlmostEqualTo(-XYZ.BasisZ))
                    {
                        if (boundaryLoops.Count > 0)
                            return null;

                        try
                        {
                            foreach (EdgeArray edgeLoop in planarFace.EdgeLoops)
                            {
                                bool hasCurve = false;
                                CurveLoop curveLoop = new CurveLoop();
                                foreach (Edge edge in edgeLoop)
                                {
                                    Curve edgeCurve = edge.AsCurveFollowingFace(planarFace);
                                    if (edgeCurve == null)
                                        return null;

                                    curveLoop.Append(edgeCurve);
                                    hasCurve = true;
                                }

                                if (!hasCurve)
                                    return null;

                                boundaryLoops.Add(curveLoop);
                            }
                        }
                        catch
                        {
                            return null;
                        }
                    }
                }
            }

            return boundaryLoops;
        }
예제 #46
0
        /// <summary>
        /// Creates an open or closed CurveLoop from a list of vertices.
        /// </summary>
        /// <param name="pointXYZs">The list of vertices.</param>
        /// <param name="points">The optional list of IFCAnyHandles that generated the vertices, used solely for error reporting.</param>
        /// <param name="id">The id of the IFCAnyHandle associated with the CurveLoop.</param>
        /// <param name="closeCurve">True if the loop needs a segment between the last point and the first point.</param>
        /// <returns>The new curve loop.</returns>
        /// <remarks>If closeCurve is true, there will be pointsXyz.Count line segments.  Otherwise, there will be pointsXyz.Count-1.</remarks>
        public static CurveLoop CreatePolyCurveLoop(IList <XYZ> pointXYZs, IList <IFCAnyHandle> points, int id, bool closeCurve)
        {
            int numPoints = pointXYZs.Count;

            if (numPoints < 2)
            {
                // TODO: log warning
                return(null);
            }

            IList <int> badIds = new List <int>();

            // The input polycurve loop may or may not repeat the start/end point.
            // wasAlreadyClosed checks if the point was repeated.
            bool wasAlreadyClosed = pointXYZs[0].IsAlmostEqualTo(pointXYZs[numPoints - 1]);

            bool wasClosed = closeCurve ? true : wasAlreadyClosed;

            // We expect at least 3 points if the curve is closed, 2 otherwise.
            int numMinPoints = wasAlreadyClosed ? 4 : (closeCurve ? 3 : 2);

            if (numPoints < numMinPoints)
            {
                // TODO: log warning
                return(null);
            }

            // Check distance between points; remove too-close points, and warn if result is non-collinear.
            // Always include first point.
            IList <XYZ> finalPoints = new List <XYZ>();

            finalPoints.Add(pointXYZs[0]);
            int numNewPoints = 1;

            int numPointsToCheck = closeCurve ? numPoints + 1 : numPoints;

            for (int ii = 1; ii < numPointsToCheck; ii++)
            {
                int nextIndex     = (ii % numPoints);
                int nextNextIndex = (nextIndex == numPoints - 1 && wasAlreadyClosed) ? 1 : ((ii + 1) % numPoints);

                // Only check if the last segment overlaps the first segment if we have a closed curve.
                bool doSegmentOverlapCheck = (ii < numPointsToCheck - 1) || wasClosed;
                if (LineSegmentIsTooShort(finalPoints[numNewPoints - 1], pointXYZs[nextIndex]) ||
                    (doSegmentOverlapCheck && LineSegmentsOverlap(finalPoints[numNewPoints - 1], pointXYZs[nextIndex], pointXYZs[nextNextIndex])))
                {
                    if (points != null)
                    {
                        badIds.Add(points[nextIndex].StepId);
                    }
                    else
                    {
                        badIds.Add(nextIndex + 1);
                    }
                }
                else
                {
                    finalPoints.Add(pointXYZs[nextIndex]);
                    numNewPoints++;
                }
            }

            // Check final segment; if too short, delete 2nd to last point instead of the last.
            if (wasClosed)
            {
                if (numNewPoints < 4)
                {
                    return(null);
                }

                bool isClosed = finalPoints[numNewPoints - 1].IsAlmostEqualTo(finalPoints[0]); // Do we have a closed loop now?
                if (wasClosed && !isClosed)                                                    // If we had a closed loop, and now we don't, fix it up.
                {
                    // Presumably, the second-to-last point had to be very close to the last point, or we wouldn't have removed the last point.
                    // So instead of creating a too-short segment, we replace the last point of the new point list with the last point of the original point list.
                    finalPoints[numNewPoints - 1] = pointXYZs[numPoints - 1];

                    // Now we have to check that we didn't inadvertently make a "too-short" segment.
                    for (int ii = numNewPoints - 1; ii > 0; ii--)
                    {
                        if (IFCGeometryUtil.LineSegmentIsTooShort(finalPoints[ii], finalPoints[ii - 1]))
                        {
                            // TODO: log this removal.
                            finalPoints.RemoveAt(ii - 1); // Remove the intermediate point, not the last point.
                            numNewPoints--;
                        }
                        else
                        {
                            break; // We are in the clear, unless we removed too many points - we've already checked the rest of the loop.
                        }
                    }
                }

                if (numNewPoints < 4)
                {
                    return(null);
                }
            }

            // This can be a very common warning, so we will restrict to verbose logging.
            if (Importer.TheOptions.VerboseLogging)
            {
                if (badIds.Count > 0)
                {
                    int    count = badIds.Count;
                    string msg   = null;
                    if (count == 1)
                    {
                        msg = "Polyline had 1 point that was too close to one of its neighbors, removing point: #" + badIds[0] + ".";
                    }
                    else
                    {
                        msg = "Polyline had " + count + " points that were too close to one of their neighbors, removing points:";
                        foreach (int badId in badIds)
                        {
                            msg += " #" + badId;
                        }
                        msg += ".";
                    }
                    Importer.TheLog.LogWarning(id, msg, false);
                }
            }

            if (numNewPoints < numMinPoints)
            {
                if (Importer.TheOptions.VerboseLogging)
                {
                    string msg = "PolyCurve had " + numNewPoints + " point(s) after removing points that were too close, expected at least " + numMinPoints + ", ignoring.";
                    Importer.TheLog.LogWarning(id, msg, false);
                }
                return(null);
            }

            CurveLoop curveLoop = new CurveLoop();

            for (int ii = 0; ii < numNewPoints - 1; ii++)
            {
                curveLoop.Append(Line.CreateBound(finalPoints[ii], finalPoints[ii + 1]));
            }

            return(curveLoop);
        }
예제 #47
0
        /// <summary>
        /// Get the curve or CurveLoop representation of IFCCurve, as a CurveLoop.  This will have a value, as long as Curve or CurveLoop do.
        /// </summary>
        public CurveLoop GetCurveLoop()
        {
            if (CurveLoop != null)
                return CurveLoop;
            if (Curve == null)
                return null;

            CurveLoop curveAsCurveLoop = new CurveLoop();
            curveAsCurveLoop.Append(Curve);
            return curveAsCurveLoop;
        }
예제 #48
0
        /// <summary>
        /// Returns a CurveLoop that has potentially been trimmed.
        /// </summary>
        /// <param name="origCurveLoop">The original curve loop.</param>
        /// <param name="startVal">The starting trim parameter.</param>
        /// <param name="origEndVal">The optional end trim parameter.  If not supplied, assume no end trim.</param>
        /// <returns>The original curve loop, if no trimming has been done, otherwise a trimmed copy.</returns>
        public static CurveLoop TrimCurveLoop(CurveLoop origCurveLoop, double startVal, double?origEndVal)
        {
            // Trivial case: no trimming.
            if (!origEndVal.HasValue && MathUtil.IsAlmostZero(startVal))
            {
                return(origCurveLoop);
            }

            IList <double> curveLengths = new List <double>();
            IList <Curve>  loopCurves   = new List <Curve>();

            double totalParamLength = 0.0;

            foreach (Curve curve in origCurveLoop)
            {
                double currLength = ScaleCurveLengthForSweptSolid(curve, curve.GetEndParameter(1) - curve.GetEndParameter(0));
                loopCurves.Add(curve);
                curveLengths.Add(currLength);
                totalParamLength += currLength;
            }

            double endVal = origEndVal.HasValue ? origEndVal.Value : totalParamLength;

            // This check allows for some leniency in the setting of startVal and endVal; we assume that if the parameter range
            // is equal, that an offset value is OK.
            if (MathUtil.IsAlmostEqual(endVal - startVal, totalParamLength))
            {
                return(origCurveLoop);
            }

            int    numCurves       = loopCurves.Count;
            double currentPosition = 0.0;
            int    currCurve       = 0;

            IList <Curve> newLoopCurves = new List <Curve>();

            if (startVal > MathUtil.Eps())
            {
                for (; currCurve < numCurves; currCurve++)
                {
                    if (currentPosition + curveLengths[currCurve] < startVal + MathUtil.Eps())
                    {
                        currentPosition += curveLengths[currCurve];
                        continue;
                    }

                    Curve newCurve = loopCurves[currCurve].Clone();
                    if (!MathUtil.IsAlmostEqual(currentPosition, startVal))
                    {
                        newCurve.MakeBound(UnscaleSweptSolidCurveParam(loopCurves[currCurve], startVal - currentPosition), newCurve.GetEndParameter(1));
                    }

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

            if (endVal < totalParamLength - MathUtil.Eps())
            {
                for (; currCurve < numCurves; currCurve++)
                {
                    if (currentPosition + curveLengths[currCurve] < endVal - MathUtil.Eps())
                    {
                        currentPosition += curveLengths[currCurve];
                        newLoopCurves.Add(loopCurves[currCurve]);
                        continue;
                    }

                    Curve newCurve = loopCurves[currCurve].Clone();
                    if (!MathUtil.IsAlmostEqual(currentPosition + curveLengths[currCurve], endVal))
                    {
                        newCurve.MakeBound(newCurve.GetEndParameter(0), UnscaleSweptSolidCurveParam(loopCurves[currCurve], endVal - currentPosition));
                    }

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

            CurveLoop trimmedCurveLoop = new CurveLoop();

            foreach (Curve curve in loopCurves)
            {
                trimmedCurveLoop.Append(curve);
            }
            return(trimmedCurveLoop);
        }
예제 #49
0
        private static CurveLoop GetFaceBoundary(Face face, EdgeArray faceBoundary, XYZ baseLoopOffset,
            bool polygonalOnly, out FaceBoundaryType faceBoundaryType)
        {
            faceBoundaryType = FaceBoundaryType.Polygonal;
            CurveLoop currLoop = new CurveLoop();
            foreach (Edge faceBoundaryEdge in faceBoundary)
            {
                Curve edgeCurve = faceBoundaryEdge.AsCurveFollowingFace(face);
                Curve offsetCurve = (baseLoopOffset != null) ? MoveCurve(edgeCurve, baseLoopOffset) : edgeCurve;
                if (!(offsetCurve is Line))
                {
                    if (polygonalOnly)
                    {
                        IList<XYZ> tessPts = offsetCurve.Tessellate();
                        int numTessPts = tessPts.Count;
                        for (int ii = 0; ii < numTessPts - 1; ii++)
                        {
                            Line line = Line.get_Bound(tessPts[ii], tessPts[ii + 1]);
                            currLoop.Append(line);
                        }
                    }
                    else
                    {
                        currLoop.Append(offsetCurve);
                    }

                    if (offsetCurve is Arc)
                        faceBoundaryType = FaceBoundaryType.LinesAndArcs;
                    else
                        faceBoundaryType = FaceBoundaryType.Complex;
                }
                else
                    currLoop.Append(offsetCurve);
            }
            return currLoop;
        }
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication app   = commandData.Application;
            UIDocument    uidoc = app.ActiveUIDocument;
            Document      doc   = uidoc.Document;

            // Retrieve selected floors, or all floors, if nothing is selected:

            List <Element> floors = new List <Element>();

            if (!Util.GetSelectedElementsOrAll(
                    floors, uidoc, typeof(Floor)))
            {
                Selection sel = uidoc.Selection;
                message = (0 < sel.GetElementIds().Count)
          ? "Please select some floor elements."
          : "No floor elements found.";
                return(Result.Failed);
            }

            // Determine top face of each selected floor:

            int         nNullFaces = 0;
            List <Face> topFaces   = new List <Face>();
            Options     opt        = app.Application.Create.NewGeometryOptions();

            foreach (Floor floor in floors)
            {
                GeometryElement geo = floor.get_Geometry(opt);

                //GeometryObjectArray objects = geo.Objects; // 2012

                foreach (GeometryObject obj in geo)
                {
                    Solid solid = obj as Solid;
                    if (solid != null)
                    {
                        PlanarFace f = GetTopFace(solid);
                        if (null == f)
                        {
                            Debug.WriteLine(
                                Util.ElementDescription(floor)
                                + " has no top face.");
                            ++nNullFaces;
                        }
                        topFaces.Add(f);
                    }
                }
            }

            using (Transaction t = new Transaction(doc))
            {
                t.Start("Create Model Lines and Floor");

                // Create new floors from the top faces found.
                // Before creating the new floor, we would obviously
                // apply whatever modifications are required to the
                // new floor profile:

                Autodesk.Revit.Creation.Application creApp = app.Application.Create;
                Autodesk.Revit.Creation.Document    creDoc = doc.Create;

                int i = 0;
                int n = topFaces.Count - nNullFaces;

                Debug.Print(
                    "{0} top face{1} found.",
                    n, Util.PluralSuffix(n));

                foreach (Face f in topFaces)
                {
                    Floor floor = floors[i++] as Floor;

                    if (null != f)
                    {
                        EdgeArrayArray eaa = f.EdgeLoops;

                        // Code for Revit 2021 and earlier:

                        //CurveArray profile; // 2021

                        #region Attempt to include inner loops
#if ATTEMPT_TO_INCLUDE_INNER_LOOPS
                        bool use_original_loops = true;
                        if (use_original_loops)
                        {
                            profile = Convert(eaa);
                        }
                        else
#endif // ATTEMPT_TO_INCLUDE_INNER_LOOPS
                        #endregion // Attempt to include inner loops

                        //{
                        //  profile = new CurveArray();

                        //  // Only use first edge array,
                        //  // the outer boundary loop,
                        //  // skip the further items
                        //  // representing holes:

                        //  EdgeArray ea = eaa.get_Item( 0 );
                        //  foreach ( Edge e in ea )
                        //  {
                        //    IList<XYZ> pts = e.Tessellate();
                        //    int m = pts.Count;
                        //    XYZ p = pts[0];
                        //    XYZ q = pts[m - 1];
                        //    Line line = Line.CreateBound( p, q );
                        //    profile.Append( line );
                        //  }
                        //}

                        List <CurveLoop> loops = new List <CurveLoop>(); // 2022

                        {
                            CurveLoop loop = new CurveLoop();

                            // Only use first edge array,
                            // the outer boundary loop,
                            // skip the further items
                            // representing holes:

                            EdgeArray ea = eaa.get_Item(0);
                            foreach (Edge e in ea)
                            {
                                IList <XYZ> pts  = e.Tessellate();
                                int         m    = pts.Count;
                                XYZ         p    = pts[0];
                                XYZ         q    = pts[m - 1];
                                Line        line = Line.CreateBound(p, q);
                                loop.Append(line);
                            }
                            loops = new List <CurveLoop>();
                            loops.Add(loop);
                        }

                        //Level level = floor.Level; // 2013

                        //Level level = doc.GetElement( floor.LevelId )
                        //  as Level; // 2014

                        // In this case we have a valid floor type given.
                        // In general, not that NewFloor will only accept
                        // floor types whose IsFoundationSlab predicate
                        // is false.

                        //floor = creDoc.NewFloor( profile, // 2021
                        //  floor.FloorType, level, true );

                        floor = Floor.Create(doc, loops,
                                             floor.FloorType.Id, floor.LevelId); // 2022

                        XYZ v = new XYZ(5, 5, 0);

                        //doc.Move( floor, v ); // 2011

                        ElementTransformUtils.MoveElement(doc, floor.Id, v); // 2012
                    }
                }
                t.Commit();
            }
            return(Result.Succeeded);
        }
예제 #51
0
        private static bool IsInRange(IFCRange range, CurveLoop loop, Plane plane, XYZ extrusionDirection, out bool clipCompletely)
        {
            clipCompletely = false;
            if (range != null)
            {
                // This check is only applicable for cuts that are perpendicular to the extrusion direction.
                // For cuts that aren't, we can't easily tell if this cut is extraneous or not.
                if (!MathUtil.IsAlmostEqual(Math.Abs(plane.Normal.DotProduct(extrusionDirection)), 1.0))
                    return true;

                double eps = MathUtil.Eps();

                double parameterValue = plane.Origin.DotProduct(extrusionDirection);

                if (range.Start > parameterValue - eps)
                {
                    clipCompletely = true;
                    return false;
                }
                if (range.End < parameterValue + eps)
                    return false;
            }

            return true;
        }
예제 #52
0
        public void Execute(UIApplication uiapp)
        {
            try
            {
                UIDocument uidoc = uiapp.ActiveUIDocument;
                Document   doc   = uidoc.Document; // myListView_ALL_Fam_Master.Items.Add(doc.GetElement(uidoc.Selection.GetElementIds().First()).Name);

                if (uidoc.Selection.GetElementIds().Count != 1)
                {
                    MessageBox.Show("Please select ONE Wall.");
                    return;
                }

                Element myElementWall = doc.GetElement(uidoc.Selection.GetElementIds().First());

                if (myElementWall.GetType() == typeof(FamilyInstance))
                {
                    FamilyInstance myFamilyInstance = myElementWall as FamilyInstance;

                    myElementWall = myFamilyInstance.Host;

                    if (myElementWall == null)
                    {
                        MessageBox.Show("Family instance must be hosted to a wall.");
                        return;
                    }
                }

                ///                             TECHNIQUE 08 OF 19 (EE08_MoveElementAroundHostingSurface.cs)
                ///↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ MOVING ELEMENTS AROUND A HOSTING SURFACE ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
                /// The people walk around the perimeter of the wall, and it will work on any surface
                ///
                ///
                /// Interfaces and ENUM's:
                ///
                ///
                /// Demonstrates classes:
                ///     Reference
                ///     Face
                ///     Transform
                ///     PlanarFace
                ///     CurveLoop
                ///
                ///
                /// Key methods:
                ///     myElementWall.GetGeometryObjectFromReference(pickedRef) as Face
                ///     pickedRef.ConvertToStableRepresentation(doc).Contains("INSTANCE"))
                ///     (myElementWall as FamilyInstance).GetTotalTransform();
                ///     myFace.GetBoundingBox().Min
                ///     myFace.Evaluate(myUV_Min)
                ///
                ///     myXYZ_FamilyTransform.OfPoint(myXYZ_CornerOne)
                ///     myXYZ_FamilyTransform.OfVector(myPlanarFace.XVector);
                ///     myCurveLoop.GetExactLength();
                ///
                ///
                ///     L1.GetEndPoint(0)).Normalize().Multiply(myDouble_ThisFarAlong);
                ///	ElementTransformUtils.MoveElement(doc, myFamilyInstance.Id, myXYZ_MoveThisMuch);
                ///
                /// * class is actually part of the .NET framework (not Revit API)
                ///
                ///
                ///
                ///	https://github.com/joshnewzealand/Revit-API-Playpen-CSharp

                List <Element> myListOfStuffOnWall = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_GenericModel).Where(x => (((FamilyInstance)x).Host != null)).Where(x => ((FamilyInstance)x).Host.Id == myElementWall.Id).ToList();
                List <Element> myListOfFurniture   = new FilteredElementCollector(doc).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_Furniture).Where(x => (((FamilyInstance)x).Host != null)).Where(x => ((FamilyInstance)x).Host.Id == myElementWall.Id).ToList();
                myListOfStuffOnWall.AddRange(myListOfFurniture);

                if (myListOfStuffOnWall.Count() > 0)
                {
                    using (Transaction tx = new Transaction(doc))
                    {
                        tx.Start("Rotate People");

                        foreach (FamilyInstance myFI in myListOfStuffOnWall)
                        {
                            FamilyInstance myFamilyInstance = myFI as FamilyInstance;

                            Reference pickedRef = myFI.HostFace;

                            ////doc.Delete(myListElementID);
                            ////myListElementID.Clear();

                            Face myFace = myElementWall.GetGeometryObjectFromReference(pickedRef) as Face;
                            if (myFace == null)
                            {
                                return;
                            }

                            Transform myXYZ_FamilyTransform = Transform.Identity;

                            if (pickedRef.ConvertToStableRepresentation(doc).Contains("INSTANCE"))
                            {
                                myXYZ_FamilyTransform = (myElementWall as FamilyInstance).GetTotalTransform();
                            }

                            Transform myTransform = Transform.Identity;

                            if (myFace.GetType() != typeof(PlanarFace))
                            {
                                return;
                            }

                            PlanarFace myPlanarFace = myFace as PlanarFace;

                            UV myUV_Min = myFace.GetBoundingBox().Min;
                            UV myUV_Max = myFace.GetBoundingBox().Max;

                            XYZ myXYZ_CornerOne = myFace.Evaluate(myUV_Min);

                            myTransform.Origin = myXYZ_FamilyTransform.OfPoint(myXYZ_CornerOne);
                            myTransform.BasisX = myXYZ_FamilyTransform.OfVector(myPlanarFace.XVector);
                            myTransform.BasisY = myXYZ_FamilyTransform.OfVector(myPlanarFace.YVector);
                            myTransform.BasisZ = myXYZ_FamilyTransform.OfVector(myPlanarFace.FaceNormal);

                            XYZ myXYZ_Centre = XYZ.Zero;

                            XYZ myXYZ_Min = new XYZ(myUV_Min.U, myUV_Min.V, 0);
                            XYZ myXYZ_Max = new XYZ(myUV_Max.U, myUV_Max.V, 0);

                            XYZ myXYZ_UV_CornerOne = (((myXYZ_Max - myXYZ_Min) * 0.1)); //; + myXYZ_Min;
                            XYZ myXYZ_UV_CornerTwo = (((myXYZ_Max - myXYZ_Min) * 0.9)); // + myXYZ_Min;

                            XYZ myXYZ_UV_Corner01 = new XYZ(myXYZ_UV_CornerOne.X, myXYZ_UV_CornerOne.Y, 0);
                            XYZ myXYZ_UV_Corner02 = new XYZ(myXYZ_UV_CornerTwo.X, myXYZ_UV_CornerOne.Y, 0);
                            XYZ myXYZ_UV_Corner03 = new XYZ(myXYZ_UV_CornerTwo.X, myXYZ_UV_CornerTwo.Y, 0);
                            XYZ myXYZ_UV_Corner04 = new XYZ(myXYZ_UV_CornerOne.X, myXYZ_UV_CornerTwo.Y, 0);

                            Line L1 = Line.CreateBound(myTransform.OfPoint(myXYZ_UV_Corner01), myTransform.OfPoint(myXYZ_UV_Corner02));
                            Line L2 = Line.CreateBound(myTransform.OfPoint(myXYZ_UV_Corner02), myTransform.OfPoint(myXYZ_UV_Corner03));
                            Line L3 = Line.CreateBound(myTransform.OfPoint(myXYZ_UV_Corner03), myTransform.OfPoint(myXYZ_UV_Corner04));
                            Line L4 = Line.CreateBound(myTransform.OfPoint(myXYZ_UV_Corner04), myTransform.OfPoint(myXYZ_UV_Corner01));

                            CurveLoop myCurveLoop = new CurveLoop();
                            myCurveLoop.Append(L1);
                            myCurveLoop.Append(L2);
                            myCurveLoop.Append(L3);
                            myCurveLoop.Append(L4);

                            double myDouble_ExactLength        = myCurveLoop.GetExactLength();
                            double myDouble_ExactLength_Twenty = myDouble_ExactLength / 40;

                            XYZ myXYZ_Result = myTransform.OfPoint((myXYZ_Max - myXYZ_Min) / 2);

                            int myIntCurrentSpinnerValue = myWindow1.myIntegerUpDown_OneToTwentyCount.Value.Value;
                            int myInt_Positioning        = (40 / myListOfStuffOnWall.Count()) * (myListOfStuffOnWall.IndexOf(myFI) + 1);
                            myIntCurrentSpinnerValue = (40 - myInt_Positioning) + myIntCurrentSpinnerValue;
                            if (myIntCurrentSpinnerValue > 40)
                            {
                                myIntCurrentSpinnerValue = myIntCurrentSpinnerValue - 40;
                            }
                            double myDouble_FutureForeach = myDouble_ExactLength_Twenty * myIntCurrentSpinnerValue;
                            double myDouble_ThisFarAlong;

                            switch (myDouble_FutureForeach)
                            {
                            case double n when n < L1.Length:

                                myDouble_ThisFarAlong = myDouble_FutureForeach;
                                myXYZ_Result          = L1.GetEndPoint(0) + (L1.GetEndPoint(1) - L1.GetEndPoint(0)).Normalize().Multiply(myDouble_ThisFarAlong);

                                break;

                            case double n when n >= L1.Length& n < L1.Length + L2.Length:

                                myDouble_ThisFarAlong = myDouble_FutureForeach - L1.Length;
                                myXYZ_Result          = L2.GetEndPoint(0) + (L2.GetEndPoint(1) - L2.GetEndPoint(0)).Normalize().Multiply(myDouble_ThisFarAlong);

                                break;

                            case double n when n >= L1.Length + L2.Length& n < L1.Length + L2.Length + L3.Length:

                                myDouble_ThisFarAlong = myDouble_FutureForeach - L1.Length - L2.Length;
                                myXYZ_Result          = L3.GetEndPoint(0) + (L3.GetEndPoint(1) - L3.GetEndPoint(0)).Normalize().Multiply(myDouble_ThisFarAlong);

                                break;

                            case double n when n >= L1.Length + L2.Length + L3.Length:

                                myDouble_ThisFarAlong = myDouble_FutureForeach - L1.Length - L2.Length - L3.Length;
                                myXYZ_Result          = L4.GetEndPoint(0) + (L4.GetEndPoint(1) - L4.GetEndPoint(0)).Normalize().Multiply(myDouble_ThisFarAlong);

                                break;
                            }

                            XYZ myXYZ_MoveThisMuch = myXYZ_Result - ((LocationPoint)myFamilyInstance.Location).Point;
                            ElementTransformUtils.MoveElement(doc, myFamilyInstance.Id, myXYZ_MoveThisMuch);

                            //SketchPlane mySketchPlane = SketchPlane.Create(doc, pickedRef);
                            //myListElementID.Add(doc.Create.NewModelCurve(L1, mySketchPlane).Id);
                            //myListElementID.Add(doc.Create.NewModelCurve(L2, mySketchPlane).Id);
                            //myListElementID.Add(doc.Create.NewModelCurve(L3, mySketchPlane).Id);
                            //myListElementID.Add(doc.Create.NewModelCurve(L4, mySketchPlane).Id);
                        }
                        tx.Commit();
                    }
                    if (myWindow1.myIntegerUpDown_OneToTwentyCount.Value.Value == 40)
                    {
                        myWindow1.myIntegerUpDown_OneToTwentyCount.Value = 0;
                    }
                    myWindow1.myIntegerUpDown_OneToTwentyCount.Value++;
                }
            }
            #region catch and finally
            catch (Exception ex)
            {
                DatabaseMethods.writeDebug("EE08_MoveElementAroundHostingSurface" + Environment.NewLine + ex.Message + Environment.NewLine + ex.InnerException, true);
            }
            finally
            {
            }
            #endregion
        }
예제 #53
0
        // return null if parent should be completely clipped.
        // TODO: determine whether or not to use face boundary.
        private static IFCAnyHandle ProcessClippingFace(ExporterIFC exporterIFC, CurveLoop outerBoundary, Plane boundaryPlane, 
            Plane extrusionBasePlane, XYZ extrusionDirection, IFCRange range, bool useFaceBoundary, IFCAnyHandle bodyItemHnd)
        {
            if (outerBoundary == null || boundaryPlane == null)
                throw new Exception("Invalid face boundary.");

            double clippingSlant = boundaryPlane.Normal.DotProduct(extrusionDirection);
            if (useFaceBoundary)
            {
                if (MathUtil.IsAlmostZero(clippingSlant))
                    return bodyItemHnd;
            }

            bool clipCompletely;
            if (!IsInRange(range, outerBoundary, boundaryPlane, extrusionDirection, out clipCompletely))
                return clipCompletely ? null : bodyItemHnd;

            if (MathUtil.IsAlmostZero(clippingSlant))
                throw new Exception("Can't create clipping perpendicular to extrusion.");

            IFCFile file = exporterIFC.GetFile();

            XYZ scaledOrig = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, boundaryPlane.Origin);
            XYZ scaledNorm = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, boundaryPlane.Normal);
            XYZ scaledXDir = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, boundaryPlane.XVec);

            IFCAnyHandle planeAxisHnd = ExporterUtil.CreateAxis(file, scaledOrig, scaledNorm, scaledXDir);
            IFCAnyHandle surfHnd = IFCInstanceExporter.CreatePlane(file, planeAxisHnd);

            IFCAnyHandle clippedBodyItemHnd = null;
            IFCAnyHandle halfSpaceHnd = null;

            if (useFaceBoundary)
            {
                IFCAnyHandle boundedCurveHnd;
                if (boundaryPlane != null)
                {
                    XYZ projScaledOrigin = ExporterIFCUtils.TransformAndScalePoint(exporterIFC, extrusionBasePlane.Origin);
                    XYZ projScaledX = ExporterIFCUtils.TransformAndScaleVector(exporterIFC, extrusionBasePlane.XVec);
                    XYZ projScaledY= ExporterIFCUtils.TransformAndScaleVector(exporterIFC, extrusionBasePlane.YVec);
                    XYZ projScaledNorm = projScaledX.CrossProduct(projScaledY);
                    
                    Plane projScaledPlane = new Plane(projScaledX, projScaledY, projScaledOrigin);

                    IList<UV> polylinePts = TransformAndProjectCurveLoopToPlane(exporterIFC, outerBoundary, projScaledPlane);
                    polylinePts.Add(polylinePts[0]);
                    boundedCurveHnd = ExporterUtil.CreatePolyline(file, polylinePts);

                    IFCAnyHandle boundedAxisHnd = ExporterUtil.CreateAxis(file, projScaledOrigin, projScaledNorm, projScaledX);

                    halfSpaceHnd = IFCInstanceExporter.CreatePolygonalBoundedHalfSpace(file, boundedAxisHnd, boundedCurveHnd, surfHnd, false);
                }
                else
                {
                    throw new Exception("Can't create non-polygonal face boundary.");
                }
            }
            else
            {
                halfSpaceHnd = IFCInstanceExporter.CreateHalfSpaceSolid(file, surfHnd, false);
            }

            if (halfSpaceHnd == null)
                throw new Exception("Can't create clipping.");

            clippedBodyItemHnd = IFCInstanceExporter.CreateBooleanClippingResult(file, IFCBooleanOperator.Difference,
                bodyItemHnd, halfSpaceHnd);
            return clippedBodyItemHnd;
        }
예제 #54
0
        /// <summary>
        ///  Exports a roof or floor as a container of multiple roof slabs.  Returns the handle, if successful.
        /// </summary>
        /// <param name="exporterIFC">The exporter.</param>
        /// <param name="ifcEnumType">The roof type.</param>
        /// <param name="element">The roof or floor element.</param>
        /// <param name="geometry">The geometry of the element.</param>
        /// <param name="productWrapper">The product wrapper.</param>
        /// <returns>The roof handle.</returns>
        /// <remarks>For floors, if there is only one component, return null, as we do not want to create a container.</remarks>
        public static IFCAnyHandle ExportRoofOrFloorAsContainer(ExporterIFC exporterIFC, string ifcEnumType, Element element, GeometryElement geometry, ProductWrapper productWrapper)
        {
            IFCFile file = exporterIFC.GetFile();

            // We support ExtrusionRoofs, FootPrintRoofs, and Floors only.
            bool elementIsRoof  = (element is ExtrusionRoof) || (element is FootPrintRoof);
            bool elementIsFloor = (element is Floor);

            if (!elementIsRoof && !elementIsFloor)
            {
                return(null);
            }

            Common.Enums.IFCEntityType elementClassTypeEnum = Common.Enums.IFCEntityType.IfcRoof;
            if (elementIsFloor)
            {
                elementClassTypeEnum = Common.Enums.IFCEntityType.IfcSlab;
            }

            // Check the intended IFC entity or type name is in the exclude list specified in the UI
            if (ExporterCacheManager.ExportOptionsCache.IsElementInExcludeList(elementClassTypeEnum))
            {
                return(null);
            }

            using (IFCTransaction transaction = new IFCTransaction(file))
            {
                using (PlacementSetter setter = PlacementSetter.Create(exporterIFC, element))
                {
                    IFCAnyHandle localPlacement = setter.LocalPlacement;
                    IList <HostObjectSubcomponentInfo> hostObjectSubcomponents = null;
                    try
                    {
                        hostObjectSubcomponents = ExporterIFCUtils.ComputeSubcomponents(element as HostObject);
                    }
                    catch
                    {
                        return(null);
                    }

                    if (hostObjectSubcomponents == null)
                    {
                        return(null);
                    }

                    int numSubcomponents = hostObjectSubcomponents.Count;
                    if (numSubcomponents == 0 || (elementIsFloor && numSubcomponents == 1))
                    {
                        return(null);
                    }

                    try
                    {
                        using (IFCExtrusionCreationData extrusionCreationData = new IFCExtrusionCreationData())
                        {
                            IFCAnyHandle ownerHistory = ExporterCacheManager.OwnerHistoryHandle;
                            extrusionCreationData.SetLocalPlacement(localPlacement);
                            extrusionCreationData.ReuseLocalPlacement = true;

                            using (TransformSetter trfSetter = TransformSetter.Create())
                            {
                                IList <GeometryObject> geometryList = new List <GeometryObject>();
                                geometryList.Add(geometry);
                                trfSetter.InitializeFromBoundingBox(exporterIFC, geometryList, extrusionCreationData);

                                IFCAnyHandle prodRepHnd = null;

                                string elementGUID = GUIDUtil.CreateGUID(element);

                                //string hostObjectType = IFCValidateEntry.GetValidIFCPredefinedType(element, ifcEnumType);

                                IFCAnyHandle hostObjectHandle = null;
                                if (elementIsRoof)
                                {
                                    hostObjectHandle = IFCInstanceExporter.CreateRoof(exporterIFC, element, elementGUID, ownerHistory,
                                                                                      localPlacement, prodRepHnd, ifcEnumType);
                                }
                                else
                                {
                                    hostObjectHandle = IFCInstanceExporter.CreateSlab(exporterIFC, element, elementGUID, ownerHistory,
                                                                                      localPlacement, prodRepHnd, ifcEnumType);
                                }

                                if (IFCAnyHandleUtil.IsNullOrHasNoValue(hostObjectHandle))
                                {
                                    return(null);
                                }

                                IList <IFCAnyHandle> elementHandles = new List <IFCAnyHandle>();
                                elementHandles.Add(hostObjectHandle);

                                // If element is floor, then the profile curve loop of hostObjectSubComponent is computed from the top face of the floor
                                // else if element is roof, then the profile curve loop is taken from the bottom face of the roof instead
                                XYZ extrusionDir = elementIsFloor ? new XYZ(0, 0, -1) : new XYZ(0, 0, 1);

                                ElementId catId = CategoryUtil.GetSafeCategoryId(element);

                                IList <IFCAnyHandle> slabHandles = new List <IFCAnyHandle>();

                                IList <CurveLoop> hostObjectOpeningLoops = new List <CurveLoop>();
                                double            maximumScaledDepth     = 0.0;

                                using (IFCExtrusionCreationData slabExtrusionCreationData = new IFCExtrusionCreationData())
                                {
                                    slabExtrusionCreationData.SetLocalPlacement(extrusionCreationData.GetLocalPlacement());
                                    slabExtrusionCreationData.ReuseLocalPlacement = false;
                                    slabExtrusionCreationData.ForceOffset         = true;

                                    int    loopNum         = 0;
                                    int    subElementStart = elementIsRoof ? (int)IFCRoofSubElements.RoofSlabStart : (int)IFCSlabSubElements.SubSlabStart;
                                    string subSlabType     = elementIsRoof ? "ROOF" : ifcEnumType;

                                    foreach (HostObjectSubcomponentInfo hostObjectSubcomponent in hostObjectSubcomponents)
                                    {
                                        trfSetter.InitializeFromBoundingBox(exporterIFC, geometryList, slabExtrusionCreationData);
                                        Plane     plane = hostObjectSubcomponent.GetPlane();
                                        Transform lcs   = GeometryUtil.CreateTransformFromPlane(plane);

                                        IList <CurveLoop> curveLoops = new List <CurveLoop>();

                                        CurveLoop slabCurveLoop = hostObjectSubcomponent.GetCurveLoop();
                                        curveLoops.Add(slabCurveLoop);
                                        double slope = Math.Abs(plane.Normal.Z);

                                        double       scaledDepth          = UnitUtil.ScaleLength(hostObjectSubcomponent.Depth);
                                        double       scaledExtrusionDepth = scaledDepth * slope;
                                        IFCAnyHandle shapeRep             = ExtrusionExporter.CreateExtrudedSolidFromCurveLoop(exporterIFC, null, curveLoops, lcs, extrusionDir, scaledExtrusionDepth, false);
                                        if (IFCAnyHandleUtil.IsNullOrHasNoValue(shapeRep))
                                        {
                                            return(null);
                                        }

                                        ElementId matId = HostObjectExporter.GetFirstLayerMaterialId(element as HostObject);
                                        BodyExporter.CreateSurfaceStyleForRepItem(exporterIFC, element.Document, shapeRep, matId);

                                        HashSet <IFCAnyHandle> bodyItems = new HashSet <IFCAnyHandle>();
                                        bodyItems.Add(shapeRep);
                                        shapeRep = RepresentationUtil.CreateSweptSolidRep(exporterIFC, element, catId, exporterIFC.Get3DContextHandle("Body"), bodyItems, null);
                                        IList <IFCAnyHandle> shapeReps = new List <IFCAnyHandle>();
                                        shapeReps.Add(shapeRep);

                                        IFCAnyHandle repHnd = IFCInstanceExporter.CreateProductDefinitionShape(file, null, null, shapeReps);

                                        // Allow support for up to 256 named IfcSlab components, as defined in IFCSubElementEnums.cs.
                                        string slabGUID = (loopNum < 256) ? GUIDUtil.CreateSubElementGUID(element, subElementStart + loopNum) : GUIDUtil.CreateGUID();

                                        IFCAnyHandle slabPlacement = ExporterUtil.CreateLocalPlacement(file, slabExtrusionCreationData.GetLocalPlacement(), null);
                                        IFCAnyHandle slabHnd       = IFCInstanceExporter.CreateSlab(exporterIFC, element, slabGUID, ownerHistory,
                                                                                                    slabPlacement, repHnd, subSlabType);

                                        //slab quantities
                                        slabExtrusionCreationData.ScaledLength         = scaledExtrusionDepth;
                                        slabExtrusionCreationData.ScaledArea           = UnitUtil.ScaleArea(UnitUtil.ScaleArea(hostObjectSubcomponent.AreaOfCurveLoop));
                                        slabExtrusionCreationData.ScaledOuterPerimeter = UnitUtil.ScaleLength(curveLoops[0].GetExactLength());
                                        slabExtrusionCreationData.Slope = UnitUtil.ScaleAngle(MathUtil.SafeAcos(Math.Abs(slope)));

                                        productWrapper.AddElement(null, slabHnd, setter, slabExtrusionCreationData, false);
                                        elementHandles.Add(slabHnd);
                                        slabHandles.Add(slabHnd);

                                        hostObjectOpeningLoops.Add(slabCurveLoop);
                                        maximumScaledDepth = Math.Max(maximumScaledDepth, scaledDepth);
                                        loopNum++;
                                    }
                                }

                                productWrapper.AddElement(element, hostObjectHandle, setter, extrusionCreationData, true);

                                ExporterUtil.RelateObjects(exporterIFC, null, hostObjectHandle, slabHandles);

                                OpeningUtil.AddOpeningsToElement(exporterIFC, elementHandles, hostObjectOpeningLoops, element, null, maximumScaledDepth,
                                                                 null, setter, localPlacement, productWrapper);

                                transaction.Commit();
                                return(hostObjectHandle);
                            }
                        }
                    }
                    finally
                    {
                        exporterIFC.ClearFaceWithElementHandleMap();
                    }
                }
            }
        }
예제 #55
0
        /// <summary>
        /// Returns a CurveLoop that has potentially been trimmed.
        /// </summary>
        /// <param name="origCurveLoop">The original curve loop.</param>
        /// <param name="startVal">The starting trim parameter.</param>
        /// <param name="origEndVal">The optional end trim parameter.  If not supplied, assume no end trim.</param>
        /// <returns>The original curve loop, if no trimming has been done, otherwise a trimmed copy.</returns>
        public static CurveLoop TrimCurveLoop(CurveLoop origCurveLoop, double startVal, double? origEndVal)
        {
            // Trivial case: no trimming.
            if (!origEndVal.HasValue && MathUtil.IsAlmostZero(startVal))
                return origCurveLoop;

            IList<double> curveLengths = new List<double>();
            IList<Curve> loopCurves = new List<Curve>();

            double totalParamLength = 0.0;
            foreach (Curve curve in origCurveLoop)
            {
                double currLength = ScaleCurveLengthForSweptSolid(curve, curve.GetEndParameter(1) - curve.GetEndParameter(0));
                loopCurves.Add(curve);
                curveLengths.Add(currLength);
                totalParamLength += currLength;
            }

            double endVal = origEndVal.HasValue ? origEndVal.Value : totalParamLength;

            // This check allows for some leniency in the setting of startVal and endVal; we assume that if the parameter range
            // is equal, that an offset value is OK.
            if (MathUtil.IsAlmostEqual(endVal - startVal, totalParamLength))
                return origCurveLoop;

            int numCurves = loopCurves.Count;
            double currentPosition = 0.0;
            int currCurve = 0;

            IList<Curve> newLoopCurves = new List<Curve>();

            if (startVal > MathUtil.Eps())
            {
                for (; currCurve < numCurves; currCurve++)
                {
                    if (currentPosition + curveLengths[currCurve] < startVal + MathUtil.Eps())
                    {
                        currentPosition += curveLengths[currCurve];
                        continue;
                    }

                    Curve newCurve = loopCurves[currCurve].Clone();
                    if (!MathUtil.IsAlmostEqual(currentPosition, startVal))
                        newCurve.MakeBound(UnscaleSweptSolidCurveParam(loopCurves[currCurve], startVal - currentPosition), newCurve.GetEndParameter(1));

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

            if (endVal < totalParamLength - MathUtil.Eps())
            {
                for (; currCurve < numCurves; currCurve++)
                {
                    if (currentPosition + curveLengths[currCurve] < endVal - MathUtil.Eps())
                    {
                        currentPosition += curveLengths[currCurve];
                        newLoopCurves.Add(loopCurves[currCurve]);
                        continue;
                    }

                    Curve newCurve = loopCurves[currCurve].Clone();
                    if (!MathUtil.IsAlmostEqual(currentPosition + curveLengths[currCurve], endVal))
                        newCurve.MakeBound(newCurve.GetEndParameter(0), UnscaleSweptSolidCurveParam(loopCurves[currCurve], endVal - currentPosition));

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

            CurveLoop trimmedCurveLoop = new CurveLoop();
            foreach (Curve curve in loopCurves)
                trimmedCurveLoop.Append(curve);
            return trimmedCurveLoop;
        }
예제 #56
0
 /// <summary>
 /// Create a swept geometry
 /// </summary>
 /// <param name="sweepPath">The sweep path, consisting of a set of contiguous curves</param>
 /// <param name="pathAttachmentCrvIdx">The index of the curve in the sweep path where the profile loops are situated</param>
 /// <param name="pathAttachmentParam">Parameter of the path curve specified by pathAttachmentCrvIdx</param>
 /// <param name="profileLoops">The curve loops defining the planar domain to be swept along the path</param>
 /// <returns>The created solid</returns>
 private Solid CreateSwept(CurveLoop sweepPath, int pathAttachmentCrvIdx, double pathAttachmentParam, List <CurveLoop> profileLoops)
 {
     return(GeometryCreationUtilities.CreateSweptGeometry(sweepPath, pathAttachmentCrvIdx, pathAttachmentParam, profileLoops));
 }
        private IList<CurveLoop> CreateProfileCurveLoopsForDirectrix(Curve directrix, out double startParam)
        {
           startParam = 0.0;

           if (directrix == null)
              return null;

           if (directrix.IsBound)
              startParam = directrix.GetEndParameter(0);

           Transform originTrf = directrix.ComputeDerivatives(startParam, false);

           if (originTrf == null)
              return null;

           // The X-dir of the transform of the start of the directrix will form the normal of the disk.
           Plane diskPlane = new Plane(originTrf.BasisX, originTrf.Origin);

           IList<CurveLoop> profileCurveLoops = new List<CurveLoop>();

           CurveLoop diskOuterCurveLoop = new CurveLoop();
           diskOuterCurveLoop.Append(Arc.Create(diskPlane, Radius, 0, Math.PI));
           diskOuterCurveLoop.Append(Arc.Create(diskPlane, Radius, Math.PI, 2.0 * Math.PI));
           profileCurveLoops.Add(diskOuterCurveLoop);

           if (InnerRadius.HasValue)
           {
              CurveLoop diskInnerCurveLoop = new CurveLoop();
              diskInnerCurveLoop.Append(Arc.Create(diskPlane, InnerRadius.Value, 0, Math.PI));
              diskInnerCurveLoop.Append(Arc.Create(diskPlane, InnerRadius.Value, Math.PI, 2.0 * Math.PI));
              profileCurveLoops.Add(diskInnerCurveLoop);
           }

           return profileCurveLoops;
        }
예제 #58
0
 /// <summary>
 /// Create a blend geometry
 /// </summary>
 /// <param name="firstLoop">The first curve loop</param>
 /// <param name="secondLoop">The second curve loop</param>
 /// <param name="vertexPairs">This input specifies how the two profile loops should be connected</param>
 /// <returns>The created solid</returns>
 private Solid CreateBlend(CurveLoop firstLoop, CurveLoop secondLoop, List <VertexPair> vertexPairs)
 {
     return(GeometryCreationUtilities.CreateBlendGeometry(firstLoop, secondLoop, vertexPairs));
 }
        /// <summary>
        /// Creates or populates Revit elements based on the information contained in this class.
        /// </summary>
        /// <param name="doc">The document.</param>
        protected override void Create(Document doc)
        {
            Transform lcs = (ObjectLocation != null) ? ObjectLocation.TotalTransform : Transform.Identity;

            // 2015+: create cone(s) for the direction of flow.
            CurveLoop rightTrangle = new CurveLoop();
            const double radius = 0.5/12.0;
            const double height = 1.5/12.0;

            SolidOptions solidOptions = new SolidOptions(ElementId.InvalidElementId, GraphicsStyleId);
            
            Frame coordinateFrame = new Frame(lcs.Origin, lcs.BasisX, lcs.BasisY, lcs.BasisZ);
            
            // The origin is at the base of the cone for everything but source - then it is at the top of the cone.
            XYZ pt1 = FlowDirection == IFCFlowDirection.Source ? lcs.Origin - height * lcs.BasisZ : lcs.Origin;
            XYZ pt2 = pt1 + radius * lcs.BasisX;
            XYZ pt3 = pt1 + height * lcs.BasisZ;
            
            rightTrangle.Append(Line.CreateBound(pt1, pt2));
            rightTrangle.Append(Line.CreateBound(pt2, pt3));
            rightTrangle.Append(Line.CreateBound(pt3, pt1));
            IList<CurveLoop> curveLoops = new List<CurveLoop>();
            curveLoops.Add(rightTrangle);

            Solid portArrow = GeometryCreationUtilities.CreateRevolvedGeometry(coordinateFrame, curveLoops, 0.0, Math.PI * 2.0, solidOptions);

            Solid oppositePortArrow = null;
            if (FlowDirection == IFCFlowDirection.SourceAndSink)
            {
                Frame oppositeCoordinateFrame = new Frame(lcs.Origin, -lcs.BasisX, lcs.BasisY, -lcs.BasisZ);
                CurveLoop oppositeRightTrangle = new CurveLoop();
                
                XYZ oppPt2 = pt1 - radius * lcs.BasisX;
                XYZ oppPt3 = pt1 - height * lcs.BasisZ;
                oppositeRightTrangle.Append(Line.CreateBound(pt1, oppPt2));
                oppositeRightTrangle.Append(Line.CreateBound(oppPt2, oppPt3));
                oppositeRightTrangle.Append(Line.CreateBound(oppPt3, pt1));
                IList<CurveLoop> oppositeCurveLoops = new List<CurveLoop>();
                oppositeCurveLoops.Add(oppositeRightTrangle);

                oppositePortArrow = GeometryCreationUtilities.CreateRevolvedGeometry(oppositeCoordinateFrame, oppositeCurveLoops, 0.0, Math.PI * 2.0, solidOptions);
            }

            if (portArrow != null)
            {
                IList<GeometryObject> geomObjs = new List<GeometryObject>();

                geomObjs.Add(portArrow);
                if (oppositePortArrow != null)
                    geomObjs.Add(oppositePortArrow);

                DirectShape directShape = IFCElementUtil.CreateElement(doc, CategoryId, GlobalId, geomObjs);
                if (directShape != null)
                {
                    CreatedGeometry = geomObjs;
                    CreatedElementId = directShape.Id;
                }
                else
                    Importer.TheLog.LogCreationError(this, null, false);
            }
        }
예제 #60
0
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            Microsoft.Office.Interop.Excel.Application xlApp      = new Microsoft.Office.Interop.Excel.Application();
            Microsoft.Office.Interop.Excel.Workbook    xlWorkbook = xlApp.Workbooks.Open(@"D:\WerkStudent\Updated\General_WithOpening");

            Microsoft.Office.Interop.Excel.Worksheet xlWorksheet = xlWorkbook.Sheets[3];
            Microsoft.Office.Interop.Excel.Range     xlRange     = xlWorksheet.UsedRange;

            int rowCount = xlRange.Rows.Count;
            int colCount = xlRange.Columns.Count;

            //Get UI document
            UIDocument uidoc = commandData.Application.ActiveUIDocument;

            //Get document
            Document doc = uidoc.Document;

            string level = (String)xlRange.Cells[3, "A"].Value2;
            //Create levels
            Level levels = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Levels)
                           .WhereElementIsNotElementType().Cast <Level>().First(x => x.Name == level);

            string ty1 = (String)xlRange.Cells[2, "A"].Value2;

            var FloorType = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_Floors)
                            .WhereElementIsElementType().Cast <FloorType>().First(x => x.Name == ty1);

            //string ty2 = (String)xlRange.Cells[2, "B"].Value2;
            ////var opening =sourceFloor.Document.Create.NewOpening(destFloor,openingCurveArray,true);
            //var Opening = new FilteredElementCollector(doc).OfCategory(BuiltInCategory.OST_FloorOpening)
            //    .WhereElementIsElementType().Cast<Opening>();



            double p01x = xlRange.Cells[4, "B"].value2;
            double p01y = xlRange.Cells[4, "C"].value2;
            double p01z = xlRange.Cells[4, "D"].value2;

            double p02x = xlRange.Cells[5, "B"].value2;
            double p02y = xlRange.Cells[5, "C"].value2;
            double p02z = xlRange.Cells[5, "D"].value2;

            double p03x = xlRange.Cells[6, "B"].value2;
            double p03y = xlRange.Cells[6, "C"].value2;
            double p03z = xlRange.Cells[6, "D"].value2;

            double p04x = xlRange.Cells[7, "B"].value2;
            double p04y = xlRange.Cells[7, "C"].value2;
            double p04z = xlRange.Cells[7, "D"].value2;

            double cF  = 1 / 0.3048;
            XYZ    p01 = new XYZ(p01x * cF, p01y * cF, p01z * cF);
            XYZ    p02 = new XYZ(p02x * cF, p02y * cF, p02z * cF);
            XYZ    p03 = new XYZ(p03x * cF, p03y * cF, p03z * cF);
            XYZ    p04 = new XYZ(p04x * cF, p04y * cF, p04z * cF);


            double p11x = xlRange.Cells[9, "B"].value2;
            double p11y = xlRange.Cells[9, "C"].value2;
            double p11z = xlRange.Cells[9, "D"].value2;

            double p12x = xlRange.Cells[10, "B"].value2;
            double p12y = xlRange.Cells[10, "C"].value2;
            double p12z = xlRange.Cells[10, "D"].value2;

            double p13x = xlRange.Cells[11, "B"].value2;
            double p13y = xlRange.Cells[11, "C"].value2;
            double p13z = xlRange.Cells[11, "D"].value2;

            double p14x = xlRange.Cells[12, "B"].value2;
            double p14y = xlRange.Cells[12, "C"].value2;
            double p14z = xlRange.Cells[12, "D"].value2;


            XYZ p11 = new XYZ(p11x * cF, p11y * cF, p11z * cF);
            XYZ p12 = new XYZ(p12x * cF, p12y * cF, p12z * cF);
            XYZ p13 = new XYZ(p13x * cF, p13y * cF, p13z * cF);
            XYZ p14 = new XYZ(p14x * cF, p14y * cF, p14z * cF);

            double pf1x = xlRange.Cells[14, "B"].value2;
            double pf1y = xlRange.Cells[14, "C"].value2;
            double pf1z = xlRange.Cells[14, "D"].value2;

            double pf2x = xlRange.Cells[15, "B"].value2;
            double pf2y = xlRange.Cells[15, "C"].value2;
            double pf2z = xlRange.Cells[15, "D"].value2;

            double pf3x = xlRange.Cells[16, "B"].value2;
            double pf3y = xlRange.Cells[16, "C"].value2;
            double pf3z = xlRange.Cells[16, "D"].value2;

            double pf4x = xlRange.Cells[17, "B"].value2;
            double pf4y = xlRange.Cells[17, "C"].value2;
            double pf4z = xlRange.Cells[17, "D"].value2;


            XYZ pf1 = new XYZ(pf1x * cF, pf1y * cF, pf1z * cF);
            XYZ pf2 = new XYZ(pf2x * cF, pf2y * cF, pf2z * cF);
            XYZ pf3 = new XYZ(pf3x * cF, pf3y * cF, pf3z * cF);
            XYZ pf4 = new XYZ(pf4x * cF, pf4y * cF, pf4z * cF);

            Line l01 = Line.CreateBound(p01, p02);
            Line l02 = Line.CreateBound(p02, p03);
            Line l03 = Line.CreateBound(p03, p04);
            Line l04 = Line.CreateBound(p04, p01);

            Line l11 = Line.CreateBound(p11, p12);
            Line l12 = Line.CreateBound(p12, p13);
            Line l13 = Line.CreateBound(p13, p14);
            Line l14 = Line.CreateBound(p14, p11);

            Line lf1 = Line.CreateBound(pf1, pf2);
            Line lf2 = Line.CreateBound(pf2, pf3);
            Line lf3 = Line.CreateBound(pf3, pf4);
            Line lf4 = Line.CreateBound(pf4, pf1);

            List <Curve> curves = new List <Curve>();

            curves.Add(l01);
            curves.Add(l02);
            curves.Add(l03);
            curves.Add(l04);

            List <Curve> curves1 = new List <Curve>();

            curves1.Add(l11);
            curves1.Add(l12);
            curves1.Add(l13);
            curves1.Add(l14);

            List <Curve> curvesf = new List <Curve>();

            curvesf.Add(lf1);
            curvesf.Add(lf2);
            curvesf.Add(lf3);
            curvesf.Add(lf4);

            // Making a curve in a loop
            CurveLoop crvloop  = CurveLoop.Create(curves);
            CurveLoop crvloop1 = CurveLoop.Create(curves1);
            CurveLoop crvloopf = CurveLoop.Create(curvesf);

            CurveLoop offcr  = CurveLoop.CreateViaOffset(crvloop, 0.1 * cF, new XYZ(0, 0, 1));
            CurveLoop offcr1 = CurveLoop.CreateViaOffset(crvloop1, 0.1 * cF, new XYZ(0, 0, 1));
            CurveLoop offcrf = CurveLoop.CreateViaOffset(crvloopf, 0.1 * cF, new XYZ(0, 0, 1));

            // Creating a curve array object required for method
            CurveArray curArr            = new CurveArray();
            CurveArray curArr1           = new CurveArray();
            CurveArray openingCurveArray = new CurveArray();


            foreach (Curve c in offcr)
            {
                //Put the curves to curve array

                curArr.Append(c);
            }
            foreach (Curve c in offcr1)
            {
                //Put the curves to curve array

                curArr1.Append(c);
            }
            foreach (Curve c in offcrf)
            {
                //Put the curves to curve array

                openingCurveArray.Append(c);
            }

            try
            {
                using (Transaction trans = new Transaction(doc, "Bungalow/Flair110/Flair152RE"))
                {
                    trans.Start();


                    doc.Create.NewFloor(curArr, FloorType, levels, false);
                    //  doc.Create.NewFloor(curArr1, FloorType, levels, false);

                    //////Floor flaw =  doc.Create.NewFloor(curArr,false);
                    //Floor fl = doc.Create.NewFloor(curArr1, FloorType, levels, false);

                    //doc.Create.NewOpening(fl, curArr1, false);


                    //XYZ openingEdges1 = pf1;
                    //XYZ openingEdges2 = pf2;
                    //XYZ openingEdges3 = pf3;
                    //XYZ openingEdges4 = pf4;

                    //var openingEdges = {openingEdges1, openingEdges2, openingEdges3, openingEdges4};

                    //var openingCurveArray = openingEdges;
                    var opening = doc.Create.NewFloor(curArr, FloorType, levels, false);

                    doc.Create.NewOpening(opening, openingCurveArray, true);


                    trans.Commit();
                }
                return(Result.Succeeded);
            }

            catch (Exception e)
            {
                message = e.Message;
                return(Result.Failed);
            }
        }