private void CreateBoxShape(IFCImportShapeEditScope shapeEditScope, Transform scaledLcs)
        {
            using (IFCImportShapeEditScope.IFCContainingRepresentationSetter repSetter = new IFCImportShapeEditScope.IFCContainingRepresentationSetter(shapeEditScope, this))
            {
                // Get the material and graphics style based in the "Box" sub-category of Generic Models.
                // We will create the sub-category if this is our first time trying to use it.
                // Note that all bounding boxes are controlled by a sub-category of Generic Models.  We may revisit that decision later.
                // Note that we hard-wire the identifier to "Box" because older files may have bounding box items in an obsolete representation.
                SolidOptions solidOptions = null;
                Category     bboxCategory = IFCCategoryUtil.GetSubCategoryForRepresentation(shapeEditScope.Document, Id, IFCRepresentationIdentifier.Box);
                if (bboxCategory != null)
                {
                    ElementId     materialId    = (bboxCategory.Material == null) ? ElementId.InvalidElementId : bboxCategory.Material.Id;
                    GraphicsStyle graphicsStyle = bboxCategory.GetGraphicsStyle(GraphicsStyleType.Projection);
                    ElementId     gstyleId      = (graphicsStyle == null) ? ElementId.InvalidElementId : graphicsStyle.Id;
                    solidOptions = new SolidOptions(materialId, gstyleId);
                }

                Solid bboxSolid = IFCGeometryUtil.CreateSolidFromBoundingBox(scaledLcs, BoundingBox, solidOptions);
                if (bboxSolid != null)
                {
                    IFCSolidInfo bboxSolidInfo = IFCSolidInfo.Create(Id, bboxSolid);
                    shapeEditScope.AddGeometry(bboxSolidInfo);
                }
            }
            return;
        }
Example #2
0
        public static void CreateSphereDirectShape(Document doc, XYZ center, float radius, string name)
        {
            List <Curve> profile = new List <Curve>();

            // first create sphere with 2' radius
            XYZ profile00    = center;
            XYZ profilePlus  = center + new XYZ(0, radius, 0);
            XYZ profileMinus = center - new XYZ(0, radius, 0);

            profile.Add(Line.CreateBound(profilePlus, profileMinus));
            profile.Add(Arc.Create(profileMinus, profilePlus, center + new XYZ(radius, 0, 0)));

            CurveLoop    curveLoop = CurveLoop.Create(profile);
            SolidOptions options   = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

            Frame frame  = new Frame(center, XYZ.BasisX, -XYZ.BasisZ, XYZ.BasisY);
            Solid sphere = GeometryCreationUtilities.CreateRevolvedGeometry(frame, new CurveLoop[] { curveLoop }, 0, 2 * Math.PI, options);

            using (Transaction t = new Transaction(doc, "Create sphere direct shape"))
            {
                t.Start();
                DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));
                ds.SetShape(new GeometryObject[] { sphere });
                ds.Name = name;
                t.Commit();
            }
        }
Example #3
0
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation scope.</param>
        /// <param name="unscaledLcs">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 unscaledLcs, Transform scaledLcs, string guid)
        {
            Transform unscaledSweptDiskPosition = (unscaledLcs == null) ? Transform.Identity : unscaledLcs;
            Transform scaledSweptDiskPosition   = (scaledLcs == null) ? Transform.Identity : scaledLcs;

            CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(Id, Directrix, StartParameter, EndParameter);

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

            CurveLoop trimmedDirectrixInWCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, Id, unscaledSweptDiskPosition, scaledSweptDiskPosition);

            // Create the disk.
            Curve firstCurve = null;

            foreach (Curve curve in trimmedDirectrixInWCS)
            {
                firstCurve = curve;
                break;
            }

            double            startParam        = 0.0;
            IList <CurveLoop> profileCurveLoops = CreateProfileCurveLoopsForDirectrix(firstCurve, out startParam);

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

            SolidOptions           solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            IList <GeometryObject> myObjs       = new List <GeometryObject>();

            try
            {
                Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInWCS, 0, startParam, profileCurveLoops,
                                                                                     solidOptions);
                if (sweptDiskSolid != null)
                {
                    myObjs.Add(sweptDiskSolid);
                }
            }
            catch (Exception ex)
            {
                // If we can't create a solid, we will attempt to split the Solid into valid pieces (that will likely have some overlap).
                if (ex.Message.Contains("self-intersections"))
                {
                    Importer.TheLog.LogWarning(Id, "The IfcSweptDiskSolid definition does not define a valid solid, likely due to self-intersections or other such problems; the profile probably extends too far toward the inner curvature of the sweep path. Creating the minimum number of solids possible to represent the geometry.", false);
                    myObjs = SplitSweptDiskIntoValidPieces(trimmedDirectrixInWCS, profileCurveLoops, solidOptions);
                }
                else
                {
                    throw ex;
                }
            }

            return(myObjs);
        }
        /// <summary>
        /// creates a DirectShape instance of which shape is Sphere.
        /// Sphere is defined by its center and radius.
        /// </summary>
        /// <param name="document">The Revit document where the instance to be drawn</param>
        /// <param name="name">The name of this instance</param>
        /// <param name="center">Position of the center</param>
        /// <param name="radius">Radius of the circle</param>
        /// <param name="line_color">Outline color of Circle</param>
        /// <param name="surface_transparency">Surface transparency; ranged from 0 (transparent) to 100 (opaque)</param>
        public DirectSphere(Document document, string name, XYZ center, double radius, Color line_color, int surface_transparency) : base(document, name)
        {
            m_shape_type = ShapeTypes.Sphere;
            Center       = center;
            Radius       = radius;

            XYZ top    = center + radius * XYZ.BasisZ;
            XYZ bottom = center - radius * XYZ.BasisZ;
            XYZ right  = center + radius * XYZ.BasisX;

            Frame frame = new Frame(center, XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ);

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

            profile.Add(Line.CreateBound(top, bottom));
            profile.Add(Arc.Create(bottom, top, right));

            CurveLoop    curve_loop = CurveLoop.Create(profile);
            SolidOptions options    = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

            if (Frame.CanDefineRevitGeometry(frame) == true)
            {
                Solid sphere = GeometryCreationUtilities.CreateRevolvedGeometry(frame, new CurveLoop[] { curve_loop }, 0, 2 * Math.PI, options);
                using (Transaction t = new Transaction(document, "Create sphere direct shape."))
                {
                    t.Start();
                    DirectShape shape = DirectShape.CreateElement(document, new ElementId(BuiltInCategory.OST_GenericModel));
                    shape.SetShape(new GeometryObject[] { sphere });
                    shape.SetName(name);
                    m_element_id = shape.Id;
                    document.ActiveView.SetElementOverrides(shape.Id, new OverrideGraphicSettings().SetProjectionLineColor(line_color).SetSurfaceTransparency(surface_transparency));
                    t.Commit();
                }
            }
        }
Example #5
0
        // Create a DirectShape Sphere
        static public void CreateSphereDirectShape(Document doc)
        {
            List <Curve> profile = new List <Curve>();

            // first create sphere with 2' radius
            XYZ    center = XYZ.Zero;
            double radius = 2.0;
            //XYZ profile00 = center;
            XYZ profilePlus  = center + new XYZ(0, radius, 0);
            XYZ profileMinus = center - new XYZ(0, radius, 0);

            profile.Add(Line.CreateBound(profilePlus, profileMinus));
            profile.Add(Arc.Create(profileMinus, profilePlus, center + new XYZ(radius, 0, 0)));

            CurveLoop    curveLoop = CurveLoop.Create(profile);
            SolidOptions options   = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

            Frame frame = new Frame(center, XYZ.BasisX, -XYZ.BasisZ, XYZ.BasisY);

            if (Frame.CanDefineRevitGeometry(frame) == true)
            {
                Solid sphere = GeometryCreationUtilities.CreateRevolvedGeometry(frame, new CurveLoop[] { curveLoop }, 0, 2 * Math.PI, options);
                using (Transaction t = new Transaction(doc, "Create sphere direct shape"))
                {
                    t.Start();
                    // create direct shape and assign the sphere shape
                    DirectShape ds = DirectShape.CreateElement(doc, new ElementId(BuiltInCategory.OST_GenericModel));

                    ds.ApplicationId     = "Application id";
                    ds.ApplicationDataId = "Geometry object id";
                    ds.SetShape(new GeometryObject[] { sphere });
                    t.Commit();
                }
            }
        }
Example #6
0
        /// <summary>
        /// Create and return a rectangular prism of the
        /// given side lengths centered at the given point.
        /// </summary>
        static Solid CreateRectangularPrism(
            XYZ center,
            double d1,
            double d2,
            double d3)
        {
            List <Curve> profile   = new List <Curve>();
            XYZ          profile00 = new XYZ(-d1 / 2, -d2 / 2, -d3 / 2);
            XYZ          profile01 = new XYZ(-d1 / 2, d2 / 2, -d3 / 2);
            XYZ          profile11 = new XYZ(d1 / 2, d2 / 2, -d3 / 2);
            XYZ          profile10 = new XYZ(d1 / 2, -d2 / 2, -d3 / 2);

            profile.Add(Line.CreateBound(profile00, profile01));
            profile.Add(Line.CreateBound(profile01, profile11));
            profile.Add(Line.CreateBound(profile11, profile10));
            profile.Add(Line.CreateBound(profile10, profile00));

            CurveLoop curveLoop = CurveLoop.Create(profile);

            SolidOptions options = new SolidOptions(
                ElementId.InvalidElementId,
                ElementId.InvalidElementId);

            return(GeometryCreationUtilities
                   .CreateExtrusionGeometry(
                       new CurveLoop[] { curveLoop },
                       XYZ.BasisZ, d3, options));
        }
Example #7
0
        /// <summary>
        ///     Creates a new DirectShape.
        /// </summary>
        /// <param name="doc"></param>
        /// <param name="parm"></param>
        /// <param name="opt"></param>
        /// <returns></returns>
        public static DirectShape CreateDirectShape(this Document doc, DirectShapeParameter parm,
                                                    SolidOptions opt = null)
        {
            if (doc == null)
            {
                throw new ArgumentNullException(nameof(doc));
            }

            if (parm == null)
            {
                throw new ArgumentNullException(nameof(parm));
            }

            var solid = CreateExtrusionGeometry(parm.Profile.ToList(), parm.Direction, parm.Distance);

            if (opt != null)
            {
                solid = CreateExtrusionGeometry(parm.Profile.ToList(), parm.Direction, parm.Distance, opt);
            }

            var result = DirectShape.CreateElement(doc, new ElementId(parm.Category));

            result?.AppendShape(new List <GeometryObject> {
                solid
            });

            return(result);
        }
        /// <summary>
        /// creates a DirectShape instance of which shape is a part of a torus (like elbow joint pipe).
        /// Torus is defined by center, axis, tube radius, and mean radius (the distance between center and tube center).
        /// The tube_begin and tube_end defines the angle between the two edges of the piece.
        /// </summary>
        /// <param name="document">The Revit document where the instance to be drawn</param>
        /// <param name="name">The name of this instance</param>
        /// <param name="center">Position of center of the torus' hole</param>
        /// <param name="axis">Vector passing through the center</param>
        /// <param name="mean_radius">The distance between torus center and its tube center</param>
        /// <param name="tube_radius">Radius of tube</param>
        /// <param name="tube_begin">The vector pointing to one of the torus' edge from its center</param>
        /// <param name="torus_angle">The angle between the tube begin and end</param>
        /// <param name="line_color">Outline color of the torus</param>
        /// <param name="surface_transparency">Surface transparency; ranged from 0 (transparent) to 100 (opaque)</param>
        public DirectTorus(Document document, string name, XYZ center, XYZ axis, double mean_radius, double tube_radius, XYZ tube_begin, double torus_angle, Color line_color, int surface_transparency) : base(document, name)
        {
            m_shape_type = ShapeTypes.Torus;
            Center       = center;
            Axis         = axis;
            MeanRadius   = mean_radius;
            TubeRadius   = tube_radius;
            HasAnElbow   = true;
            TubeBegin    = tube_begin;
            TubeAngle    = torus_angle;

            XYZ    tilting_axis  = XYZ.BasisZ.CrossProduct(axis);
            double tilting_angle = FindSurfaceRevitPluginUtils.GetPositiveAngleBetween(XYZ.BasisZ, axis, tilting_axis);

            bool      no_need_to_tilt = tilting_axis.IsAlmostEqualTo(XYZ.Zero);
            Transform tilting_torus   = no_need_to_tilt ? Transform.Identity : Transform.CreateRotation(tilting_axis, tilting_angle);
            XYZ       tilted_basis_x  = tilting_torus.OfVector(XYZ.BasisX);

            // model space coordinates
            Frame frame = new Frame(XYZ.Zero, XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ);

            XYZ model_tube_center = XYZ.BasisX * mean_radius;
            XYZ model_tube_top    = model_tube_center + tube_radius * XYZ.BasisZ;
            XYZ model_tube_bottom = model_tube_center - tube_radius * XYZ.BasisZ;
            XYZ model_tube_outer  = model_tube_center + tube_radius * XYZ.BasisX;
            XYZ model_tube_inner  = model_tube_center - tube_radius * XYZ.BasisX;

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

            tube_circle.Add(Arc.Create(model_tube_top, model_tube_bottom, model_tube_inner));
            tube_circle.Add(Arc.Create(model_tube_bottom, model_tube_top, model_tube_outer));

            CurveLoop    curve_loop = CurveLoop.Create(tube_circle);
            SolidOptions options    = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

            if (Frame.CanDefineRevitGeometry(frame))
            {
                Solid torus = GeometryCreationUtilities.CreateRevolvedGeometry(frame, new CurveLoop[] { curve_loop }, 0, torus_angle, options);
                using (Transaction t = new Transaction(document, "Create torus direct shape."))
                {
                    t.Start();
                    DirectShape shape = DirectShape.CreateElement(document, new ElementId(BuiltInCategory.OST_GenericModel));
                    shape.SetShape(new GeometryObject[] { torus });
                    shape.SetName(name);
                    m_element_id = shape.Id;

                    if (no_need_to_tilt == false)
                    {
                        shape.Location.Rotate(Line.CreateUnbound(XYZ.Zero, tilting_axis), tilting_angle);
                    }
                    shape.Location.Rotate(Line.CreateUnbound(XYZ.Zero, axis), FindSurfaceRevitPluginUtils.GetPositiveAngleBetween(tilted_basis_x, tube_begin, axis));
                    shape.Location.Move(center);

                    document.ActiveView.SetElementOverrides(shape.Id, new OverrideGraphicSettings().SetProjectionLineColor(line_color).SetSurfaceTransparency(surface_transparency));
                    t.Commit();
                }
            }
        }
Example #9
0
        protected List <GeometryObject> CreateConformalGeometryIfPossible(
            IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs)
        {
            Transform unscaledSweptDiskPosition = (unscaledLcs == null) ? Transform.Identity : unscaledLcs;

            IList <CurveLoop> trimmedDirectrices = IFCGeometryUtil.TrimCurveLoops(Id, Directrix, StartParameter, EndParameter);

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

            List <GeometryObject> myObjs = null;
            bool isIdentity = unscaledSweptDiskPosition.IsIdentity;

            foreach (CurveLoop trimmedDirectrix in trimmedDirectrices)
            {
                // Create the disk.
                Curve firstCurve = null;
                foreach (Curve curve in trimmedDirectrix)
                {
                    firstCurve = curve;
                    break;
                }

                double            startParam        = 0.0;
                IList <CurveLoop> profileCurveLoops = CreateProfileCurveLoopsForDirectrix(firstCurve, out startParam);
                if (profileCurveLoops == null)
                {
                    return(null);
                }

                SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
                myObjs = new List <GeometryObject>();

                try
                {
                    Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrix, 0, startParam, profileCurveLoops,
                                                                                         solidOptions);
                    if (!isIdentity)
                    {
                        sweptDiskSolid = SolidUtils.CreateTransformed(sweptDiskSolid, unscaledSweptDiskPosition);
                    }

                    if (sweptDiskSolid != null)
                    {
                        myObjs.Add(sweptDiskSolid);
                    }
                }
                catch
                {
                    return(null);
                }
            }

            return(myObjs);
        }
Example #10
0
        /// <summary>
        /// creates a DirectShape instance of which shape is Plane.
        /// Plane is defined by four vertices (top-left, top-right, bottom-left, bottom-right) on the plane.
        /// (Actually, it is a rectangle as you already know.)
        /// </summary>
        /// <remarks>The Plane has very small thickness (0.0039) since there is no way to create a plane with no thickness using DirectShape.</remarks>
        /// <param name="document">The Revit document where the instance to be drawn</param>
        /// <param name="name">The name of this instance</param>
        /// <param name="top_left">Position of the top-left vertex</param>
        /// <param name="top_right">Position of the top-right vertex</param>
        /// <param name="bottom_left">Position of the bottom-left vertex</param>
        /// <param name="bottom_right">Position of the bottom-right vertex</param>
        /// <param name="line_color">Outline color of Plane</param>
        /// <param name="surface_transparency">Surface transparency; ranged from 0 (transparent) to 100 (opaque)</param>
        public DirectPlane(Document document, string name, XYZ top_left, XYZ top_right, XYZ bottom_left, XYZ bottom_right, Color line_color, int surface_transparency) : base(document, name)
        {
            m_shape_type = ShapeTypes.Plane;
            TopLeft      = top_left;
            TopRight     = top_right;
            BottomLeft   = bottom_left;
            BottomRight  = bottom_right;

            XYZ    rotation_axis, translation_offset;
            double rotation_angle;
            XYZ    tl, tr;
            XYZ    bl, br;

            // We'll rotates and translates the plane transformed to be axis-aligned, because GeometryCreationUtilities.CreateSweptGeometry may fail to define a plane due to the precision issue.
            GetAxisAlignedPlane(
                top_left, top_right, bottom_left, bottom_right,
                out tl, out tr, out bl, out br,
                out rotation_axis, out rotation_angle, out translation_offset);

            Frame frame = new Frame(XYZ.Zero, XYZ.BasisX, XYZ.BasisY, XYZ.BasisZ);

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

            profile.Add(Line.CreateBound(tl, bl));
            profile.Add(Line.CreateBound(bl, br));
            profile.Add(Line.CreateBound(br, tr));
            profile.Add(Line.CreateBound(tr, tl));

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

            swept_profile.Add(Line.CreateBound(XYZ.Zero, 0.0039 * XYZ.BasisZ));

            CurveLoop    curve_loop = CurveLoop.Create(profile);
            CurveLoop    sweep_path = CurveLoop.Create(swept_profile);
            SolidOptions options    = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

            if (Frame.CanDefineRevitGeometry(frame) == true)
            {
                Solid thin_box = GeometryCreationUtilities.CreateSweptGeometry(sweep_path, 0, 0, new CurveLoop[] { curve_loop }, options);
                using (Transaction t = new Transaction(document, "Create plane direct shape"))
                {
                    t.Start();
                    DirectShape shape = DirectShape.CreateElement(document, new ElementId(BuiltInCategory.OST_GenericModel));
                    shape.SetShape(new GeometryObject[] { thin_box });
                    shape.SetName(name);
                    m_element_id = shape.Id;
                    shape.Location.Rotate(Line.CreateUnbound(XYZ.Zero, rotation_axis), -rotation_angle);
                    shape.Location.Move(-translation_offset);
                    document.ActiveView.SetElementOverrides(shape.Id, new OverrideGraphicSettings().SetProjectionLineColor(line_color).SetSurfaceTransparency(surface_transparency));
                    t.Commit();
                }
            }
        }
Example #11
0
        private bool CreateRoomMassByBoundingBox(Room room)
        {
            try
            {
                var bb  = room.get_BoundingBox(null);
                var eid = new ElementId(BuiltInCategory.OST_Mass);

                if (bb == null)
                {
                    return(false);
                }

                    #if REVIT2019 || REVIT2018 || REVIT2017 || REVIT2020 || REVIT2021
                DirectShape roomShape = DirectShape.CreateElement(doc, eid);
                    #else
                DirectShape roomShape = DirectShape.CreateElement(doc, eid, "A", "B");
                    #endif

                var curves = new List <Curve>();

                var bl = new XYZ(bb.Min.X, bb.Min.Y, bb.Min.Z);
                var br = new XYZ(bb.Max.X, bb.Min.Y, bb.Min.Z);
                var tr = new XYZ(bb.Max.X, bb.Max.Y, bb.Min.Z);
                var tl = new XYZ(bb.Min.X, bb.Max.Y, bb.Min.Z);

                var height = bb.Max.Z - bb.Min.Z;

                curves.Add(Line.CreateBound(bl, br));
                curves.Add(Line.CreateBound(br, tr));
                curves.Add(Line.CreateBound(tr, tl));
                curves.Add(Line.CreateBound(tl, bl));
                var loop      = CurveLoop.Create(curves);
                var options   = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);
                var roomSolid = GeometryCreationUtilities.CreateExtrusionGeometry(new[] { loop }, new XYZ(0, 0, 1), height, options);

                if (roomSolid != null)
                {
                    var geomObj = new GeometryObject[] { roomSolid };
                    if (geomObj.Length > 0)
                    {
                        roomShape.SetShape(geomObj);
                        CopyAllRoomParametersToMasses(room, roomShape);
                        return(true);
                    }
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
            }
            return(false);
        }
        /// <summary>
        /// creates a DirectShape instance of which shape is Torus.
        /// Torus is defined by center, axis, tube radius, and mean radius (the distance between center and tube center).
        /// </summary>
        /// <param name="document">The Revit document where the instance to be drawn</param>
        /// <param name="name">The name of this instance</param>
        /// <param name="center">Position of center of the torus' hole</param>
        /// <param name="axis">Vector passing through the center</param>
        /// <param name="mean_radius">The distance between the center and tube center</param>
        /// <param name="tube_radius">Radius of tube</param>
        /// <param name="line_color">Outline color</param>
        /// <param name="surface_transparency">Surface transparency; ranged from 0 (transparent) to 100 (opaque)</param>
        public DirectTorus(Document document, string name, XYZ center, XYZ axis, double mean_radius, double tube_radius, Color line_color, int surface_transparency) : base(document, name)
        {
            m_shape_type = ShapeTypes.Torus;
            Center       = center;
            Axis         = axis;
            MeanRadius   = mean_radius;
            TubeRadius   = tube_radius;
            HasAnElbow   = false;
            TubeBegin    = new XYZ();
            TubeAngle    = 0.0;

            XYZ axis_norm    = axis.Normalize();
            XYZ minor_center = ((XYZ.BasisX.CrossProduct(axis_norm).GetLength() < Double.Epsilon) ? XYZ.BasisY : XYZ.BasisX).CrossProduct(axis_norm);

            minor_center = center + minor_center.Normalize() * mean_radius;

            XYZ basis_z = axis.Normalize();
            XYZ basis_x = (minor_center - center).Normalize();
            XYZ basis_y = basis_z.CrossProduct(basis_x).Normalize();

            Frame frame = new Frame(center, basis_x, basis_y, basis_z);

            // model space coordinates
            XYZ near  = minor_center - tube_radius * basis_x;
            XYZ far   = minor_center + tube_radius * basis_x;
            XYZ back  = minor_center + tube_radius * basis_z;
            XYZ front = minor_center - tube_radius * basis_z;

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

            profile.Add(Arc.Create(near, far, front));
            profile.Add(Arc.Create(far, near, back));

            CurveLoop    curve_loop = CurveLoop.Create(profile);
            SolidOptions options    = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

            if (Frame.CanDefineRevitGeometry(frame) == true)
            {
                Solid torus = GeometryCreationUtilities.CreateRevolvedGeometry(frame, new CurveLoop[] { curve_loop }, 0, 2 * Math.PI, options);
                using (Transaction t = new Transaction(document, "Create torus direct shape"))
                {
                    t.Start();
                    DirectShape shape = DirectShape.CreateElement(document, new ElementId(BuiltInCategory.OST_GenericModel));
                    shape.SetShape(new GeometryObject[] { torus });
                    shape.SetName(name);
                    document.ActiveView.SetElementOverrides(shape.Id, new OverrideGraphicSettings().SetProjectionLineColor(line_color).SetSurfaceTransparency(surface_transparency));
                    t.Commit();
                }
            }
        }
Example #13
0
        /// <summary>
        /// creates a DirectShape instance of which shape is Cylinder.
        /// Cylinder is defined by two circles (top, bottom) with the same radius.
        /// </summary>
        /// <param name="document">The Revit document where the instance to be drawn</param>
        /// <param name="name">The name of this instance</param>
        /// <param name="doc">The Revit document where the instance to be drawn</param>
        /// <param name="top">Position of center of the top circle</param>
        /// <param name="bottom">Position of center of the bottom circle</param>
        /// <param name="radius">Radius of the circles</param>
        /// <param name="line_color">Outline color of Cylinder</param>
        /// <param name="surface_transparency">Surface transparency; ranged from 0 (transparent) to 100 (opaque)</param>
        public DirectCylinder(Document document, string name, XYZ top, XYZ bottom, double radius, Color line_color, int surface_transparency) : base(document, name)
        {
            m_shape_type = ShapeTypes.Cylinder;
            Top          = top;
            Bottom       = bottom;
            Radius       = radius;

            // defines a reference frame of which origin is at the center of the cylinder and z-axis is passing through the centers of its top and bottom.
            XYZ center  = (top + bottom) / 2;
            XYZ basis_z = (top - bottom).Normalize();
            XYZ basis_x = XYZ.BasisY.CrossProduct(basis_z).Normalize();
            XYZ basis_y = basis_z.CrossProduct(basis_x).Normalize();

            Frame frame = new Frame(center, basis_x, basis_y, basis_z);

            XYZ bottom_left  = bottom - radius * basis_x;
            XYZ bottom_right = bottom + radius * basis_x;
            XYZ bottom_front = bottom - radius * basis_y;
            XYZ bottom_back  = bottom + radius * basis_y;

            // creates a profile that is a cross section of a circle (the cylinder will be made by sweeping through the z-axis).
            List <Curve> profile = new List <Curve>();

            profile.Add(Arc.Create(bottom_left, bottom_right, bottom_back));
            profile.Add(Arc.Create(bottom_right, bottom_left, bottom_front));

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

            swept_profile.Add(Line.CreateBound(bottom, top));

            CurveLoop    curve_loop = CurveLoop.Create(profile);
            CurveLoop    sweep_path = CurveLoop.Create(swept_profile);
            SolidOptions options    = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

            if (Frame.CanDefineRevitGeometry(frame) == true)
            {
                Solid cylinder = GeometryCreationUtilities.CreateSweptGeometry(sweep_path, 0, 0, new CurveLoop[] { curve_loop }, options);
                using (Transaction t = new Transaction(document, "Create cylinder direct shape"))
                {
                    t.Start();
                    DirectShape shape = DirectShape.CreateElement(document, new ElementId(BuiltInCategory.OST_GenericModel));
                    shape.SetShape(new GeometryObject[] { cylinder });
                    shape.SetName(name);
                    m_element_id = shape.Id;
                    document.ActiveView.SetElementOverrides(shape.Id, new OverrideGraphicSettings().SetProjectionLineColor(line_color).SetSurfaceTransparency(surface_transparency));
                    t.Commit();
                }
            }
        }
Example #14
0
 public static Solid CreateRectangularPrism(XYZ center, double d1, double d2, double d3)
 {
     List<Curve> list = new List<Curve>();
     XYZ xYZ = new XYZ((0.0 - d1) / 2.0, (0.0 - d2) / 2.0, (0.0 - d3) / 2.0);
     XYZ xYZ2 = new XYZ((0.0 - d1) / 2.0, d2 / 2.0, (0.0 - d3) / 2.0);
     XYZ xYZ3 = new XYZ(d1 / 2.0, d2 / 2.0, (0.0 - d3) / 2.0);
     XYZ xYZ4 = new XYZ(d1 / 2.0, (0.0 - d2) / 2.0, (0.0 - d3) / 2.0);
     list.Add(Line.CreateBound(xYZ, xYZ2));
     list.Add(Line.CreateBound(xYZ2, xYZ3));
     list.Add(Line.CreateBound(xYZ3, xYZ4));
     list.Add(Line.CreateBound(xYZ4, xYZ));
     CurveLoop curveLoop = CurveLoop.Create(list);
     SolidOptions solidOptions = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);
     return GeometryCreationUtilities.CreateExtrusionGeometry(new CurveLoop[1]
     {
     curveLoop
     }, XYZ.BasisZ, d3, solidOptions);
 }
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>One or more created Solids.</returns>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            Transform origLCS = (lcs == null) ? Transform.Identity : lcs;
            Transform unscaledRevolvePosition = (Position == null) ? origLCS : origLCS.Multiply(Position);

            Transform scaledOrigLCS         = (scaledLcs == null) ? Transform.Identity : scaledLcs;
            Transform scaledRevolvePosition = (Position == null) ? scaledOrigLCS : scaledOrigLCS.Multiply(Position);

            ISet <IList <CurveLoop> > disjointLoops = GetTransformedCurveLoops(unscaledRevolvePosition, scaledRevolvePosition);

            if (disjointLoops == null || disjointLoops.Count() == 0)
            {
                return(null);
            }

            XYZ          frameOrigin  = scaledRevolvePosition.OfPoint(Axis.Origin);
            XYZ          frameZVec    = scaledRevolvePosition.OfVector(Axis.BasisZ);
            SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);

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

            foreach (IList <CurveLoop> loops in disjointLoops)
            {
                XYZ frameXVec = null;

                frameXVec = GetValidXVectorFromLoop(loops[0], frameZVec, frameOrigin);
                if (frameXVec == null)
                {
                    Importer.TheLog.LogError(Id, "Couldn't generate valid frame for IfcRevolvedAreaSolid.", false);
                    return(null);
                }
                XYZ   frameYVec       = frameZVec.CrossProduct(frameXVec);
                Frame coordinateFrame = new Frame(frameOrigin, frameXVec, frameYVec, frameZVec);

                GeometryObject myObj = GeometryCreationUtilities.CreateRevolvedGeometry(coordinateFrame, loops, 0, Angle, solidOptions);
                if (myObj != null)
                {
                    myObjs.Add(myObj);
                }
            }

            return(myObjs);
        }
Example #16
0
        private bool CreateSimpleRoomMassByExtrusion(Room room)
        {
            try
            {
                var height = room.LookupParameter("Limit Offset");
                var curves = new List <CurveLoop>();
                var spatialBoundaryOptions = new SpatialElementBoundaryOptions {
                    StoreFreeBoundaryFaces = true
                };
                var loop             = new CurveLoop();
                var boundarySegments = room.GetBoundarySegments(spatialBoundaryOptions);
                var biggestList      = boundarySegments.OrderByDescending(item => item.Count).First();

                foreach (var seg in biggestList)
                {
                    loop.Append(seg.GetCurve());
                }

                curves.Add(loop);

                var options   = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);
                var roomSolid = GeometryCreationUtilities.CreateExtrusionGeometry(curves, new XYZ(0, 0, 1), height.AsDouble(), options);

                if (roomSolid == null)
                {
                    return(false);
                }

                var eid = new ElementId(BuiltInCategory.OST_Mass);
                #if REVIT2019 || REVIT2018 || REVIT2017 || REVIT2020 || REVIT2021
                DirectShape roomShape = DirectShape.CreateElement(doc, eid);
                #else
                DirectShape roomShape = DirectShape.CreateElement(doc, eid, "A", "B");
                #endif
                roomShape.SetShape(new GeometryObject[] { roomSolid });
                CopyAllRoomParametersToMasses(room, roomShape);
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine(ex.Message);
                return(false);
            }
            return(true);
        }
        private static Solid CreateWallEndClippedWallGeometry(Wall wallElement, IList<IList<IFCConnectedWallData>> connectedWalls,
            Curve baseCurve, double unscaledWidth, double scaledDepth)
        {
            CurveLoop newLoop = SafeCreateViaThicken(baseCurve, unscaledWidth);
            if (newLoop == null)
                return null;

            IList<CurveLoop> boundaryLoops = new List<CurveLoop>();
            boundaryLoops.Add(newLoop);

            XYZ normal = XYZ.BasisZ;
            SolidOptions solidOptions = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);
            double unscaledDepth = UnitUtil.UnscaleLength(scaledDepth);
            Solid baseSolid = GeometryCreationUtilities.CreateExtrusionGeometry(boundaryLoops, normal, scaledDepth, solidOptions);

            if (!GetDifferenceFromWallJoins(wallElement.Document, wallElement.Id, baseSolid, connectedWalls))
                return null;

            return baseSolid;
        }
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The geometry creation scope.</param>
        /// <param name="unscaledLcs">The unscaled local coordinate system for the geometry, if the scaled version isn't supported downstream.</param>
        /// <param name="scaledLcs">The scaled (true) local coordinate system for the geometry.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform unscaledLcs, Transform scaledLcs, string guid)
        {
            Transform unscaledObjectPosition = (unscaledLcs == null) ? Position : unscaledLcs.Multiply(Position);
            Transform scaledObjectPosition   = (scaledLcs == null) ? Position : scaledLcs.Multiply(Position);

            CurveLoop baseProfileCurve = Directrix.GetCurveLoop();

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

            CurveLoop trimmedDirectrix = IFCGeometryUtil.TrimCurveLoop(Id, baseProfileCurve, StartParameter, EndParameter);

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

            double    startParam  = 0.0; // If the directrix isn't bound, this arbitrary parameter will do.
            Transform originTrf0  = null;
            Curve     firstCurve0 = trimmedDirectrix.First();

            if (firstCurve0.IsBound)
            {
                startParam = firstCurve0.GetEndParameter(0);
            }
            originTrf0 = firstCurve0.ComputeDerivatives(startParam, false);
            if (originTrf0 == null)
            {
                return(null);
            }

            // Note: the computation of the reference Surface Local Transform must be done before the directrix is transform to LCS (because the ref surface isn't)
            //     and therefore the origin is at the start of the curve should be the start of the directrix that lies on the surface.
            //     This is needed to transform the swept area that must be perpendicular to the start of the directrix curve

            Transform referenceSurfaceLocalTransform = ReferenceSurface.GetTransformAtPoint(originTrf0.Origin);

            CurveLoop trimmedDirectrixInLCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, Id, unscaledObjectPosition, scaledObjectPosition);

            // Create the sweep.
            Transform originTrf  = null;
            Curve     firstCurve = trimmedDirectrixInLCS.First();

            //if (firstCurve.IsBound)
            //    startParam = firstCurve.GetEndParameter(0);
            originTrf = firstCurve.ComputeDerivatives(startParam, false);

            Transform unscaledReferenceSurfaceTransform = unscaledObjectPosition.Multiply(referenceSurfaceLocalTransform);
            Transform scaledReferenceSurfaceTransform   = scaledObjectPosition.Multiply(referenceSurfaceLocalTransform);

            Transform profileCurveLoopsTransform = Transform.CreateTranslation(originTrf.Origin);

            profileCurveLoopsTransform.BasisX = scaledReferenceSurfaceTransform.BasisZ;
            profileCurveLoopsTransform.BasisZ = originTrf.BasisX.Normalize();
            profileCurveLoopsTransform.BasisY = profileCurveLoopsTransform.BasisZ.CrossProduct(profileCurveLoopsTransform.BasisX);

            ISet <IList <CurveLoop> > profileCurveLoops = GetTransformedCurveLoops(profileCurveLoopsTransform, profileCurveLoopsTransform);

            if (profileCurveLoops == null || profileCurveLoops.Count == 0)
            {
                return(null);
            }

            SolidOptions           solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            IList <GeometryObject> myObjs       = new List <GeometryObject>();

            foreach (IList <CurveLoop> loops in profileCurveLoops)
            {
                GeometryObject myObj = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInLCS, 0, startParam, loops, solidOptions);
                if (myObj != null)
                {
                    myObjs.Add(myObj);
                }
            }

            return(myObjs);
        }
        /// <summary>
        /// Return a solid corresponding to the volume represented by boundingBoxXYZ.
        /// </summary>
        /// <param name="lcs">The local coordinate system of the bounding box; if null, assume the Identity transform.</param>
        /// <param name="boundingBoxXYZ">The bounding box.</param>
        /// <param name="solidOptions">The options for creating the solid.  Allow null to mean default.</param>
        /// <returns>A solid of the same size and orientation as boundingBoxXYZ, or null if boundingBoxXYZ is invalid or null.</returns>
        /// <remarks>We don't do any checking on the input transform, which could have non-uniform scaling and/or mirroring.
        /// This could potentially lead to unexpected results, which we can examine if and when such cases arise.</remarks>
        public static Solid CreateSolidFromBoundingBox(Transform lcs, BoundingBoxXYZ boundingBoxXYZ, SolidOptions solidOptions)
        {
            // Check that the bounding box is valid.
            if (boundingBoxXYZ == null || !boundingBoxXYZ.Enabled)
            {
                return(null);
            }

            try
            {
                // Create a transform based on the incoming local coordinate system and the bounding box coordinate system.
                Transform bboxTransform = (lcs == null) ? boundingBoxXYZ.Transform : lcs.Multiply(boundingBoxXYZ.Transform);

                XYZ[] profilePts = new XYZ[4];
                profilePts[0] = bboxTransform.OfPoint(boundingBoxXYZ.Min);
                profilePts[1] = bboxTransform.OfPoint(new XYZ(boundingBoxXYZ.Max.X, boundingBoxXYZ.Min.Y, boundingBoxXYZ.Min.Z));
                profilePts[2] = bboxTransform.OfPoint(new XYZ(boundingBoxXYZ.Max.X, boundingBoxXYZ.Max.Y, boundingBoxXYZ.Min.Z));
                profilePts[3] = bboxTransform.OfPoint(new XYZ(boundingBoxXYZ.Min.X, boundingBoxXYZ.Max.Y, boundingBoxXYZ.Min.Z));

                XYZ upperRightXYZ = bboxTransform.OfPoint(boundingBoxXYZ.Max);

                // If we assumed that the transforms had no scaling,
                // then we could simply take boundingBoxXYZ.Max.Z - boundingBoxXYZ.Min.Z.
                // This code removes that assumption.
                XYZ origExtrusionVector = new XYZ(boundingBoxXYZ.Min.X, boundingBoxXYZ.Min.Y, boundingBoxXYZ.Max.Z) - boundingBoxXYZ.Min;
                XYZ extrusionVector     = bboxTransform.OfVector(origExtrusionVector);

                double extrusionDistance  = extrusionVector.GetLength();
                XYZ    extrusionDirection = extrusionVector.Normalize();

                CurveLoop baseLoop = new CurveLoop();

                for (int ii = 0; ii < 4; ii++)
                {
                    baseLoop.Append(Line.CreateBound(profilePts[ii], profilePts[(ii + 1) % 4]));
                }

                IList <CurveLoop> baseLoops = new List <CurveLoop>();
                baseLoops.Add(baseLoop);

                if (solidOptions == null)
                {
                    return(GeometryCreationUtilities.CreateExtrusionGeometry(baseLoops, extrusionDirection, extrusionDistance));
                }
                else
                {
                    return(GeometryCreationUtilities.CreateExtrusionGeometry(baseLoops, extrusionDirection, extrusionDistance, solidOptions));
                }
            }
            catch
            {
                return(null);
            }
        }
Example #20
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);
        }
        private void CreateBoxShape(IFCImportShapeEditScope shapeEditScope, Transform scaledLcs)
        {
            using (IFCImportShapeEditScope.IFCContainingRepresentationSetter repSetter = new IFCImportShapeEditScope.IFCContainingRepresentationSetter(shapeEditScope, this))
            {
                // Get the material and graphics style based in the "Box" sub-category of Generic Models.  
                // We will create the sub-category if this is our first time trying to use it.
                // Note that all bounding boxes are controlled by a sub-category of Generic Models.  We may revisit that decision later.
                SolidOptions solidOptions = null;
                Category bboxCategory = IFCCategoryUtil.GetSubCategoryForRepresentation(shapeEditScope.Document, Id, Identifier);
                if (bboxCategory != null)
                {
                    ElementId materialId = (bboxCategory.Material == null) ? ElementId.InvalidElementId : bboxCategory.Material.Id;
                    GraphicsStyle graphicsStyle = bboxCategory.GetGraphicsStyle(GraphicsStyleType.Projection);
                    ElementId gstyleId = (graphicsStyle == null) ? ElementId.InvalidElementId : graphicsStyle.Id;
                    solidOptions = new SolidOptions(materialId, gstyleId);
                }

                Solid bboxSolid = IFCGeometryUtil.CreateSolidFromBoundingBox(scaledLcs, BoundingBox, solidOptions);
                if (bboxSolid != null)
                {
                    IFCSolidInfo bboxSolidInfo = IFCSolidInfo.Create(Id, bboxSolid);
                    shapeEditScope.AddGeometry(bboxSolidInfo);
                }
            }
            return;
        }
      /// <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, null);
         }

         IList<GeometryObject> returnList = new List<GeometryObject>();
         returnList.Add(baseSolid);
         return returnList;
      }
      /// <summary>
      /// Return geometry for a particular representation item.
      /// </summary>
      /// <param name="shapeEditScope">The shape edit scope.</param>
      /// <param name="lcs">Local coordinate system for the geometry.</param>
      /// <param name="guid">The guid of an element for which represntation is being created.</param>
      /// <returns>One or more created geometries.</returns>
      /// <remarks>The scaledLcs is only partially supported in this routine; it allows scaling the depth of the extrusion,
      /// which is commonly found in ACA files.</remarks>
      protected override IList<GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
      {
         if (Direction == null)
         {
            Importer.TheLog.LogError(Id, "Error processing IfcExtrudedAreaSolid, can't create geometry.", false);
            return null;
         }

         Transform origLCS = (lcs == null) ? Transform.Identity : lcs;
         Transform origScaledLCS = (scaledLcs == null) ? Transform.Identity : scaledLcs;

         Transform extrusionPosition = (Position == null) ? origLCS : origLCS.Multiply(Position);
         Transform scaledExtrusionPosition = (Position == null) ? origScaledLCS : origScaledLCS.Multiply(Position);

         XYZ extrusionDirection = extrusionPosition.OfVector(Direction);

         ISet<IList<CurveLoop>> disjointLoops = GetTransformedCurveLoops(extrusionPosition);
         if (disjointLoops == null || disjointLoops.Count() == 0)
            return null;

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

         foreach (IList<CurveLoop> loops in disjointLoops)
         {
            SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            XYZ scaledDirection = scaledExtrusionPosition.OfVector(Direction);
            double currDepth = Depth * scaledDirection.GetLength();

            GeometryObject extrusionObject = null;
            try
            {
               // We may try to create separate extrusions, one per layer here.
               bool shouldWarn = false;
               ElementId overrideMaterialId = ElementId.InvalidElementId;
               IList<GeometryObject> extrusionLayers = CreateGeometryFromMaterialLayerUsage(shapeEditScope, extrusionPosition, loops,
                   extrusionDirection, currDepth, out overrideMaterialId, out shouldWarn);

               if (extrusionLayers == null || extrusionLayers.Count == 0)
               {
                  if (shouldWarn)
                     Importer.TheLog.LogWarning(Id, "Couldn't process associated IfcMaterialLayerSetUsage, using body geometry instead.", false);
                  if (overrideMaterialId != ElementId.InvalidElementId)
                     solidOptions.MaterialId = overrideMaterialId;
                  extrusionObject = GeometryCreationUtilities.CreateExtrusionGeometry(loops, extrusionDirection, currDepth, solidOptions);
               }
               else
               {
                  foreach (GeometryObject extrusionLayer in extrusionLayers)
                     extrusions.Add(extrusionLayer);
               }
            }
            catch (Exception ex)
            {
               if (shapeEditScope.MustCreateSolid())
                  throw ex;

               Importer.TheLog.LogError(Id, "Extrusion has an invalid definition for a solid; reverting to mesh.", false);

               MeshFromGeometryOperationResult meshResult = TessellatedShapeBuilder.CreateMeshByExtrusion(
                  loops, extrusionDirection, currDepth, GetMaterialElementId(shapeEditScope));

               // will throw if mesh is not available
               extrusionObject = meshResult.GetMesh();
            }

            if (extrusionObject != null)
               extrusions.Add(extrusionObject);
         }

         return extrusions;
      }
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>One or more created Solids.</returns>
        protected override IList<GeometryObject> CreateGeometryInternal(
              IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            Transform origLCS = (lcs == null) ? Transform.Identity : lcs;
            Transform revolvePosition = (Position == null) ? origLCS : origLCS.Multiply(Position);

            ISet<IList<CurveLoop>> disjointLoops = GetTransformedCurveLoops(revolvePosition);
            if (disjointLoops == null || disjointLoops.Count() == 0)
                return null;

            XYZ frameOrigin = revolvePosition.OfPoint(Axis.Origin);
            XYZ frameZVec = revolvePosition.OfVector(Axis.BasisZ);
            SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            
            IList<GeometryObject> myObjs = new List<GeometryObject>();

            foreach (IList<CurveLoop> loops in disjointLoops)
            {
                XYZ frameXVec = null;

                frameXVec = GetValidXVectorFromLoop(loops[0], frameZVec, frameOrigin);
                if (frameXVec == null)
                {
                    Importer.TheLog.LogError(Id, "Couldn't generate valid frame for IfcRevolvedAreaSolid.", false);
                    return null;
                }
                XYZ frameYVec = frameZVec.CrossProduct(frameXVec);
                Frame coordinateFrame = new Frame(frameOrigin, frameXVec, frameYVec, frameZVec);

                GeometryObject myObj = GeometryCreationUtilities.CreateRevolvedGeometry(coordinateFrame, loops, 0, Angle, solidOptions);
                if (myObj != null)
                    myObjs.Add(myObj);
            }

            return myObjs;
        }
Example #25
0
        /// <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;

            // 2016+ only.
            Point point = Point.Create(lcs.Origin, GraphicsStyleId);

            // 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>();

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

                DirectShape directShape = IFCElementUtil.CreateElement(doc, CategoryId, GlobalId, geomObjs, Id);
                if (directShape != null)
                {
                    CreatedGeometry  = geomObjs;
                    CreatedElementId = directShape.Id;
                }
                else
                {
                    Importer.TheLog.LogCreationError(this, null, false);
                }
            }
        }
Example #26
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument    uidoc = uiapp.ActiveUIDocument;
            Document      doc   = uidoc.Document;

            //EDGE PATH
            Reference edgeBack = uidoc.Selection.PickObject(ObjectType.Edge, "Select long edge");

            //EDGE DIRECTION
            Reference edgeDirRef = uidoc.Selection.PickObject(ObjectType.Edge, "Select edge for direction");

            //EDGE
            Element        edgeBackElement = doc.GetElement(edgeBack);
            GeometryObject edgeBackObject  = edgeBackElement.GetGeometryObjectFromReference(edgeBack);
            Edge           elemEdge        = edgeBackObject as Edge;
            Curve          edgeBackCurve   = elemEdge.AsCurve();

            XYZ edgeBackDir = edgeBackCurve.GetEndPoint(1) - edgeBackCurve.GetEndPoint(0);


            //POINT ORDER: 1-5 back edge - extrusion path, 0-1 walkway width

            /*
             * 3
             |       2
             |       |
             |       |
             |       |            5
             | 0       |
             |      1
             */



            XYZ pt5 = edgeBackCurve.GetEndPoint(0);

            //pt5 should be the lowest Z point
            if (pt5.Z > edgeBackCurve.GetEndPoint(1).Z)
            {
                pt5 = edgeBackCurve.GetEndPoint(1);
            }

            //EDGE DIRECTION
            Element        edgeDirElement = doc.GetElement(edgeDirRef);
            GeometryObject edgeDirObject  = edgeDirElement.GetGeometryObjectFromReference(edgeDirRef);
            Edge           edgeDirEdge    = edgeDirObject as Edge;
            Curve          edgeDirCurve   = edgeDirEdge.AsCurve();

            XYZ edgeDirDir = edgeDirCurve.GetEndPoint(1) - edgeDirCurve.GetEndPoint(0);

            double scale  = 304.8;
            double offset = 1030 / scale;   //distance from back edge to baseplate
            double width  = 850 / scale;    //egress width

            //PROFILE
            XYZ pt0 = edgeDirCurve.GetEndPoint(0);     //towards tunnel
            XYZ pt1 = edgeBackCurve.GetEndPoint(0);    //towards earth

            //XYZ pt2 = new XYZ(pt1.X, pt1.Y, pt1.Z+(2100/scale));


            if (edgeDirCurve.GetEndPoint(0).DistanceTo(edgeBackCurve.GetEndPoint(0)) <
                edgeDirCurve.GetEndPoint(1).DistanceTo(edgeBackCurve.GetEndPoint(0)))
            {
                pt1 = edgeDirCurve.GetEndPoint(0);
                pt0 = edgeDirCurve.GetEndPoint(1);
            }
            else
            {
                pt1 = edgeDirCurve.GetEndPoint(1);
                pt0 = edgeDirCurve.GetEndPoint(0);
            }

            //XYZ perpVector = edgeDirDir.CrossProduct(edgeBackDir).Normalize();
            //XYZ perpVector = (pt5 - pt1).CrossProduct(pt0 - pt1).Normalize();

            //XYZ BASE Z
            XYZ perpVector = (new XYZ(pt1.X, pt1.Y, pt1.Z + 1) - pt1).Normalize();

            pt1 = pt1 + (pt0 - pt1).Normalize() * (offset - width);
            pt0 = pt1 + (pt0 - pt1).Normalize() * width;

            XYZ pt2 = pt1 + perpVector * 2100 / scale;
            //XYZ pt3 = new XYZ(pt0.X, pt0.Y, pt0.Z+(2100/scale));
            XYZ pt3 = pt0 + perpVector * 2100 / scale;

            //TOP FACE PLANE
            //Plane topPlane = Plane.CreateByThreePoints(pt0, pt1, pt5);

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

            //START CURVELOOP

            Line crv0 = Line.CreateBound(pt1, pt0);
            Line crv1 = Line.CreateBound(pt0, pt3);
            Line crv2 = Line.CreateBound(pt3, pt2);
            Line crv3 = Line.CreateBound(pt2, pt1);

            CurveLoop profileLoop = CurveLoop.Create(new List <Curve> {
                crv0, crv1, crv2, crv3
            });

            //PrintPoint(pt0, 1);
            //PrintPoint(pt1, 1);
            //PrintPoint(pt2, 1);

            //VERTICAL PLANE
            Plane p = Plane.CreateByThreePoints(pt0, pt1, pt2);


            //END CURVE LOOP
            Transform tf = Transform.CreateTranslation(edgeBackDir);

            Curve crv0tr = crv0.CreateTransformed(tf);
            Curve crv1tr = crv1.CreateTransformed(tf);
            Curve crv2tr = crv2.CreateTransformed(tf);
            Curve crv3tr = crv3.CreateTransformed(tf);

            CurveLoop profileLoopEnd = CurveLoop.Create(new List <Curve> {
                crv0tr, crv1tr, crv2tr, crv3tr
            });

            Plane pEnd = Plane.CreateByThreePoints(crv0tr.GetEndPoint(0), crv0tr.GetEndPoint(1), crv1tr.GetEndPoint(1));

            //			WireframeBuilder builder = new WireframeBuilder();
            //
            //			builder.AddCurve(edgeBackCurve);

            ElementId categoryId = new ElementId(BuiltInCategory.OST_GenericModel);

            SolidOptions options = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);


            using (Transaction t = new Transaction(doc, "Create model curves"))
            {
                t.Start();

                try
                {
                    //Solid sweep = GeometryCreationUtilities.CreateSweptGeometry(path, 0, edgeBackCurve.ComputeRawParameter(0.5), new List<CurveLoop> { profileLoop });
                    Solid loop = GeometryCreationUtilities.CreateLoftGeometry(new List <CurveLoop> {
                        profileLoop, profileLoopEnd
                    }, options);

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

                    //ds.SetShape(builder);

                    ds.SetShape(new GeometryObject[] { loop });
                }
                catch (Exception ex)
                {
                    TaskDialog.Show("Error", ex.Message);
                }

                //SketchPlane sp = SketchPlane.Create(doc, p);
                //SketchPlane spTop = SketchPlane.Create(doc, topPlane);
                //SketchPlane spEnd = SketchPlane.Create(doc, pEnd);


                //doc.Create.NewModelCurve(edgeBackCurve, spTop);
                //    doc.Create.NewModelCurve(crv0, sp);
                //    doc.Create.NewModelCurve(crv1, sp);
                //    doc.Create.NewModelCurve(crv2, sp);
                //    doc.Create.NewModelCurve(crv3, sp);

                //doc.Create.NewModelCurve(crv0tr, spEnd);
                //doc.Create.NewModelCurve(crv1tr, spEnd);
                //doc.Create.NewModelCurve(crv2tr, spEnd);
                //doc.Create.NewModelCurve(crv3tr, spEnd);

                t.Commit();
            }


            TaskDialog.Show("R", PrintPoint(edgeBackCurve.GetEndPoint(0), scale) + ";\n" +
                            PrintPoint(edgeBackCurve.GetEndPoint(1), scale) + ";\n" +
                            PrintPoint(edgeDirCurve.GetEndPoint(0), scale));

            return(Result.Succeeded);
        }
        /// <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.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        protected override IList<GeometryObject> CreateGeometryInternal(
              IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            Transform objectPosition = (lcs == null) ? Position : lcs.Multiply(Position);

            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, objectPosition);

            // Create the sweep.
            double startParam = 0.0; // If the directrix isn't bound, this arbitrary parameter will do.
            Transform originTrf = null;
            Curve firstCurve = trimmedDirectrixInLCS.First();
            if (firstCurve.IsBound)
                startParam = firstCurve.GetEndParameter(0);
            originTrf = firstCurve.ComputeDerivatives(startParam, false);

            if (originTrf == null)
                return null;

            Transform referenceSurfaceLocalTransform = ReferenceSurface.GetTransformAtPoint(originTrf.Origin);
            Transform referenceSurfaceTransform = objectPosition.Multiply(referenceSurfaceLocalTransform);

            Transform profileCurveLoopsTransform = Transform.CreateTranslation(originTrf.Origin);
            profileCurveLoopsTransform.BasisX = referenceSurfaceTransform.BasisZ;
            profileCurveLoopsTransform.BasisZ = originTrf.BasisX.Normalize();
            profileCurveLoopsTransform.BasisY = profileCurveLoopsTransform.BasisZ.CrossProduct(profileCurveLoopsTransform.BasisX);

            ISet<IList<CurveLoop>> profileCurveLoops = GetTransformedCurveLoops(profileCurveLoopsTransform);
            if (profileCurveLoops == null || profileCurveLoops.Count == 0)
                return null;

            SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            IList<GeometryObject> myObjs = new List<GeometryObject>();
            foreach (IList<CurveLoop> loops in profileCurveLoops)
            {
                GeometryObject myObj = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInLCS, 0, startParam, loops, solidOptions);
                if (myObj != null)
                    myObjs.Add(myObj);
            }

            return myObjs;
        }
        private GeometryObject CreateGeometryFromMateriaProfile(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);
        }
        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;
        }
        // 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 ||
                    !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);
        }
Example #31
0
        public Result Execute(
            ExternalCommandData commandData,
            ref string message,
            ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument    uidoc = uiapp.ActiveUIDocument;
            Application   app   = uiapp.Application;
            Document      doc   = uidoc.Document;

            string id_addin = uiapp.ActiveAddInId.GetGUID()
                              .ToString();

            IEnumerable <Room> rooms
                = new FilteredElementCollector(doc)
                  .WhereElementIsNotElementType()
                  .OfClass(typeof(SpatialElement))
                  .Where(e => e.GetType() == typeof(Room))
                  .Cast <Room>();

            // Collect room data for glTF export

            List <GltfNodeData> room_data = new List <GltfNodeData>(
                rooms.Count <Room>());

            // Collect geometry data for glTF: a list of
            // vertex coordinates in millimetres, and a list
            // of triangle vertex indices into the coord list.

            List <IntPoint3d>      gltf_coords  = new List <IntPoint3d>();
            List <TriangleIndices> gltf_indices = new List <TriangleIndices>();

            using (Transaction tx = new Transaction(doc))
            {
                tx.Start("Generate Direct Shape Elements "
                         + "Representing Room Volumes");

                foreach (Room r in rooms)
                {
                    Debug.Print("Processing "
                                + r.Name + "...");

                    // Collect data for current room

                    GltfNodeData rd = new GltfNodeData(r);

                    GeometryElement geo = r.ClosedShell;

                    Debug.Assert(
                        geo.First <GeometryObject>() is Solid,
                        "expected a solid for room closed shell");

                    Solid solid = geo.First <GeometryObject>() as Solid;

                    #region Fix the shape
#if FIX_THE_SHAPE_SOMEHOW
                    // Create IList step by step

                    Solid solid = geo.First <GeometryObject>()
                                  as Solid;

                    // The room closed shell solid faces have a
                    // non-null graphics style id:
                    // Interior Fill 106074
                    // The sphere faces' graphics style id is null.
                    // Maybe this graphics style does something
                    // weird in the Forge viewer?
                    // Let's create a copy of the room solid and
                    // see whether that resets the graphics style.

                    solid = SolidUtils.CreateTransformed(
                        solid, Transform.Identity);

                    shape = new GeometryObject[] { solid };

                    // Create a sphere

                    var    center = XYZ.Zero;
                    double radius = 2.0;

                    var p = center + radius * XYZ.BasisY;
                    var q = center - radius * XYZ.BasisY;

                    var profile = new List <Curve>();
                    profile.Add(Line.CreateBound(p, q));
                    profile.Add(Arc.Create(q, p,
                                           center + radius * XYZ.BasisX));

                    var curveLoop = CurveLoop.Create(profile);

                    var options = new SolidOptions(
                        ElementId.InvalidElementId,  // material
                        ElementId.InvalidElementId); // graphics style

                    var frame = new Frame(center,
                                          XYZ.BasisX, -XYZ.BasisZ, XYZ.BasisY);

                    var sphere = GeometryCreationUtilities
                                 .CreateRevolvedGeometry(frame,
                                                         new CurveLoop[] { curveLoop },
                                                         0, 2 * Math.PI, options);

                    shape = new GeometryObject[] { solid, sphere };
#endif // #if FIX_THE_SHAPE_SOMEHOW
                    #endregion // Fix the shape

                    IList <GeometryObject> shape
                        = geo.ToList <GeometryObject>();

                    // Previous counts define offsets
                    // to new binary data

                    rd.CoordinatesBegin = gltf_coords.Count;
                    rd.TriangleVertexIndicesBegin
                        = gltf_indices.Count;

                    // Create a new solid to use for the direct
                    // shape from the flawed solid returned by
                    // GetClosedShell and gather glTF facet data

                    shape = CopyGeometry(geo,
                                         ElementId.InvalidElementId,
                                         gltf_coords, gltf_indices);

                    rd.CoordinatesCount = gltf_coords.Count
                                          - rd.CoordinatesBegin;

                    rd.TriangleVertexIndexCount
                        = gltf_indices.Count
                          - rd.TriangleVertexIndicesBegin;

                    IEnumerable <IntPoint3d> pts
                        = gltf_coords.Skip <IntPoint3d>(
                              rd.CoordinatesBegin);

                    rd.Min = new IntPoint3d(
                        pts.Min <IntPoint3d, int>(p => p.X),
                        pts.Min <IntPoint3d, int>(p => p.Y),
                        pts.Min <IntPoint3d, int>(p => p.Z));
                    rd.Max = new IntPoint3d(
                        pts.Max <IntPoint3d, int>(p => p.X),
                        pts.Max <IntPoint3d, int>(p => p.Y),
                        pts.Max <IntPoint3d, int>(p => p.Z));

                    Dictionary <string, string> param_values
                        = GetParamValues(r);

                    string json = FormatDictAsJson(param_values);

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

                    ds.ApplicationId     = id_addin;
                    ds.ApplicationDataId = r.UniqueId;
                    ds.SetShape(shape);
                    ds.get_Parameter(_bip_properties).Set(json);
                    ds.Name = "Room volume for " + r.Name;
                    room_data.Add(rd);
                }
                tx.Commit();
            }

            // Save glTF text and binary data to two files;
            // metadata, min, max, buffer information;
            // vertex coordinates and triangle indices

            // Path.GetTempPath() returns a weird subdirectory
            // created by Revit, so we will not use that here, e.g.,
            // C:\Users\tammikj\AppData\Local\Temp\bfd59506-2dff-4b0f-bbe4-31587fcaf508

            //string path = Path.GetTempPath();

            string path = "C:/tmp";

            path = Path.Combine(path, doc.Title + "_gltf");

            using (StreamWriter s = new StreamWriter(
                       path + ".txt"))
            {
                int n = room_data.Count;

                s.WriteLine("{0} room{1}", n, ((1 == n) ? "" : "s"));
                s.WriteLine("{0},{1},{2},{3},{4},{5},{6},{7},{8}",
                            "id",   // "ElementId",
                            "uid",  // "UniqueId",
                            "name", // "RoomName",
                            "min",
                            "max",
                            "coord begin",   // "CoordinatesBegin",
                            "count",         // "CoordinatesCount",
                            "indices begin", // "TriangleVertexIndicesBegin",
                            "count");        // "TriangleVertexIndexCount"

                foreach (GltfNodeData rd in room_data)
                {
                    s.WriteLine(rd.ToString());
                }
            }

            using (FileStream f = File.Create(path + ".bin"))
            {
                using (BinaryWriter writer = new BinaryWriter(f))
                {
                    foreach (IntPoint3d p in gltf_coords)
                    {
                        writer.Write((float)p.X);
                        writer.Write((float)p.Y);
                        writer.Write((float)p.Z);
                    }
                    foreach (TriangleIndices ti in gltf_indices)
                    {
                        foreach (int i in ti.Indices)
                        {
                            Debug.Assert(ushort.MaxValue > i,
                                         "expected vertex index to fit into unsigned short");

                            writer.Write((ushort)i);
                        }
                    }
                }
            }
            return(Result.Succeeded);
        }
Example #32
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.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>The created geometry.</returns>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            Transform objectPosition = (lcs == null) ? Position : lcs.Multiply(Position);

            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, objectPosition);

            // Create the sweep.
            double    startParam = 0.0; // If the directrix isn't bound, this arbitrary parameter will do.
            Transform originTrf  = null;
            Curve     firstCurve = trimmedDirectrixInLCS.First();

            if (firstCurve.IsBound)
            {
                startParam = firstCurve.GetEndParameter(0);
            }
            originTrf = firstCurve.ComputeDerivatives(startParam, false);

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

            Transform referenceSurfaceLocalTransform = ReferenceSurface.GetTransformAtPoint(originTrf.Origin);
            Transform referenceSurfaceTransform      = objectPosition.Multiply(referenceSurfaceLocalTransform);

            Transform profileCurveLoopsTransform = Transform.CreateTranslation(originTrf.Origin);

            profileCurveLoopsTransform.BasisX = referenceSurfaceTransform.BasisZ;
            profileCurveLoopsTransform.BasisZ = originTrf.BasisX.Normalize();
            profileCurveLoopsTransform.BasisY = profileCurveLoopsTransform.BasisZ.CrossProduct(profileCurveLoopsTransform.BasisX);

            ISet <IList <CurveLoop> > profileCurveLoops = GetTransformedCurveLoops(profileCurveLoopsTransform);

            if (profileCurveLoops == null || profileCurveLoops.Count == 0)
            {
                return(null);
            }

            SolidOptions           solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
            IList <GeometryObject> myObjs       = new List <GeometryObject>();

            foreach (IList <CurveLoop> loops in profileCurveLoops)
            {
                GeometryObject myObj = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInLCS, 0, startParam, loops, solidOptions);
                if (myObj != null)
                {
                    myObjs.Add(myObj);
                }
            }

            return(myObjs);
        }
        /// <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 unscaledLcs, 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] {
                unscaledLcs.OfPoint((xVec * -largeCoordinateValue) + (yVec * -largeCoordinateValue) + origin),
                unscaledLcs.OfPoint((xVec * largeCoordinateValue) + (yVec * -largeCoordinateValue) + origin),
                unscaledLcs.OfPoint((xVec * largeCoordinateValue) + (yVec * largeCoordinateValue) + origin),
                unscaledLcs.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       = unscaledLcs.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 unscaledTotalTransform = unscaledLcs.Multiply(BaseBoundingCurveTransform);
                Transform scaledTotalTransform   = scaledLcs.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);

                unscaledTotalTransform = unscaledTotalTransform.Multiply(moveBaseTransform);
                scaledTotalTransform   = scaledTotalTransform.Multiply(moveBaseTransform);

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

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

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

            returnList.Add(baseSolid);
            return(returnList);
        }
        public static void DoJob(DesignAutomationData data)
        {
            if (data == null)
            {
                throw new ArgumentNullException(nameof(data));
            }

            Application rvtApp = data.RevitApp;

            if (rvtApp == null)
            {
                throw new InvalidDataException(nameof(rvtApp));
            }

            string modelPath = data.FilePath;

            if (String.IsNullOrWhiteSpace(modelPath))
            {
                throw new InvalidDataException(nameof(modelPath));
            }

            Document rvtDoc = data.RevitDoc;

            if (rvtDoc == null)
            {
                throw new InvalidOperationException("Could not open document!");
            }

            //add shared parameter definition
            AddSetOfSharedParameters(rvtDoc);

            try
            {
                // Deleting existing DirectShape
                // might need to filter out the shapes for room only?
                // get ready to filter across just the elements visible in a view
                FilteredElementCollector coll = new FilteredElementCollector(rvtDoc);
                coll.OfClass(typeof(DirectShape));
                IEnumerable <DirectShape> DSdelete = coll.Cast <DirectShape>();

                using (Transaction tx = new Transaction(rvtDoc))
                {
                    tx.Start("Delete Direct Shape");

                    try
                    {
                        foreach (DirectShape ds in DSdelete)
                        {
                            ICollection <ElementId> ids = rvtDoc.Delete(ds.Id);
                        }

                        tx.Commit();
                    }
                    catch (ArgumentException)
                    {
                        tx.RollBack();
                        throw new InvalidOperationException("Delete Direct Shape Failed!");
                    }
                }

                //get all rooms
                FilteredElementCollector m_Collector = new FilteredElementCollector(rvtDoc);
                m_Collector.OfCategory(BuiltInCategory.OST_Rooms);
                IList <Element> m_Rooms  = m_Collector.ToElements();
                int             roomNbre = 0;

                ElementId roomId = null;

                //  Iterate the list and gather a list of boundaries
                foreach (Room room in m_Rooms)
                {
                    //  Avoid unplaced rooms
                    if (room.Area > 1)
                    {
                        String _family_name = "testRoom-" + room.UniqueId.ToString();

                        using (Transaction tr = new Transaction(rvtDoc))
                        {
                            tr.Start("Create Mass");

                            // Found BBOX

                            BoundingBoxXYZ bb = room.get_BoundingBox(null);
                            XYZ            pt = new XYZ((bb.Min.X + bb.Max.X) / 2, (bb.Min.Y + bb.Max.Y) / 2, bb.Min.Z);


                            //  Get the room boundary
                            IList <IList <BoundarySegment> > boundaries = room.GetBoundarySegments(new SpatialElementBoundaryOptions()); // 2012


                            // a room may have a null boundary property:
                            int n = 0;

                            if (null != boundaries)
                            {
                                n = boundaries.Count;
                            }


                            //  The array of boundary curves
                            CurveArray m_CurveArray = new CurveArray();


                            // Add Direct Shape
                            List <CurveLoop> curveLoopList = new List <CurveLoop>();

                            if (0 < n)
                            {
                                int iBoundary = 0, iSegment;

                                foreach (IList <BoundarySegment> b in boundaries) // 2012
                                {
                                    List <Curve> profile = new List <Curve>();
                                    ++iBoundary;
                                    iSegment = 0;

                                    foreach (BoundarySegment s in b)
                                    {
                                        ++iSegment;
                                        Curve curve = s.GetCurve(); // 2016
                                        profile.Add(curve);         //add shape for instant object
                                    }


                                    try
                                    {
                                        CurveLoop curveLoop = CurveLoop.Create(profile);
                                        curveLoopList.Add(curveLoop);
                                    }
                                    catch (Exception ex)
                                    {
                                        //Debug.WriteLine(ex.Message);
                                    }
                                }
                            }

                            try
                            {
                                SolidOptions options = new SolidOptions(ElementId.InvalidElementId, ElementId.InvalidElementId);

                                Frame frame = new Frame(pt, XYZ.BasisX, -XYZ.BasisZ, XYZ.BasisY);

                                //  Simple insertion point
                                XYZ pt1 = new XYZ(0, 0, 0);
                                //  Our normal point that points the extrusion directly up
                                XYZ ptNormal = new XYZ(0, 0, 100);
                                //  The plane to extrude the mass from
                                Plane       m_Plane       = Plane.CreateByNormalAndOrigin(ptNormal, pt1);
                                SketchPlane m_SketchPlane = SketchPlane.Create(rvtDoc, m_Plane); // 2014

                                Location loc = room.Location;

                                LocationPoint lp = loc as LocationPoint;

                                Level oBelow = getNearestBelowLevel(rvtDoc, lp.Point.Z);
                                Level oUpper = getNearestUpperLevel(rvtDoc, lp.Point.Z);

                                double height = oUpper.Elevation - oBelow.Elevation;

                                Solid roomSolid;
                                roomSolid = GeometryCreationUtilities.CreateExtrusionGeometry(curveLoopList, ptNormal, height);

                                DirectShape ds = DirectShape.CreateElement(rvtDoc, new ElementId(BuiltInCategory.OST_GenericModel));

                                ds.SetShape(new GeometryObject[] { roomSolid });

                                roomId = ds.Id;


                                roomNbre += 1;
                                tr.Commit();
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.Message);
                            }
                        }

                        using (Transaction tx = new Transaction(rvtDoc))
                        {
                            tx.Start("Change P");

                            Element   readyDS = rvtDoc.GetElement(roomId);
                            Parameter p       = readyDS.LookupParameter("RoomNumber");
                            if (p != null)
                            {
                                p.Set(room.Number.ToString());
                            }
                            tx.Commit();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new InvalidOperationException(ex.ToString());
            }
        }
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>One or more created geometries.</returns>
        /// <remarks>The scaledLcs is only partially supported in this routine; it allows scaling the depth of the extrusion,
        /// which is commonly found in ACA files.</remarks>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            if (Direction == null)
            {
                Importer.TheLog.LogError(Id, "Error processing IfcExtrudedAreaSolid, can't create geometry.", false);
                return(null);
            }

            Transform origLCS       = (lcs == null) ? Transform.Identity : lcs;
            Transform origScaledLCS = (scaledLcs == null) ? Transform.Identity : scaledLcs;

            Transform unscaledExtrusionPosition = (Position == null) ? origLCS : origLCS.Multiply(Position);
            Transform scaledExtrusionPosition   = (Position == null) ? origScaledLCS : origScaledLCS.Multiply(Position);

            XYZ scaledExtrusionDirection = scaledExtrusionPosition.OfVector(Direction);

            ISet <IList <CurveLoop> > disjointLoops = GetTransformedCurveLoops(unscaledExtrusionPosition, scaledExtrusionPosition);

            if (disjointLoops == null || disjointLoops.Count() == 0)
            {
                return(null);
            }

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

            foreach (IList <CurveLoop> originalLoops in disjointLoops)
            {
                SolidOptions solidOptions    = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
                XYZ          scaledDirection = scaledExtrusionPosition.OfVector(Direction);
                double       currDepth       = Depth * scaledDirection.GetLength();

                IList <CurveLoop> loops = new List <CurveLoop>();
                foreach (CurveLoop originalLoop in originalLoops)
                {
                    if (!originalLoop.IsOpen())
                    {
                        loops.Add(originalLoop);
                        continue;
                    }

                    if (originalLoop.Count() > 0)
                    {
                        try
                        {
                            // We will attempt to close the loop to make it usable.
                            XYZ       startPoint      = originalLoop.First().GetEndPoint(0);
                            XYZ       endPoint        = originalLoop.Last().GetEndPoint(1);
                            Line      closingLine     = Line.CreateBound(endPoint, startPoint);
                            CurveLoop healedCurveLoop = CurveLoop.CreateViaCopy(originalLoop);
                            healedCurveLoop.Append(closingLine);
                            loops.Add(healedCurveLoop);
                            Importer.TheLog.LogWarning(Id, "Extrusion has an open profile loop, fixing.", false);
                            continue;
                        }
                        catch
                        {
                        }
                    }

                    Importer.TheLog.LogError(Id, "Extrusion has an open profile loop, ignoring.", false);
                }

                if (loops.Count == 0)
                {
                    continue;
                }

                GeometryObject extrusionObject = null;
                try
                {
                    // We may try to create separate extrusions, one per layer here.
                    bool      shouldWarn         = false;
                    ElementId overrideMaterialId = ElementId.InvalidElementId;

                    if (shapeEditScope.Creator.MaterialSelect != null)
                    {
                        if (shapeEditScope.Creator.MaterialSelect is IFCMaterialLayerSetUsage)
                        {
                            IList <GeometryObject> extrusionLayers = CreateGeometryFromMaterialLayerUsage(shapeEditScope, scaledExtrusionPosition, loops,
                                                                                                          scaledExtrusionDirection, currDepth, out overrideMaterialId, out shouldWarn);
                            if (extrusionLayers == null || extrusionLayers.Count == 0)
                            {
                                if (shouldWarn)
                                {
                                    Importer.TheLog.LogWarning(Id, "Couldn't process associated IfcMaterialLayerSetUsage, using body geometry instead.", false);
                                }
                                if (overrideMaterialId != ElementId.InvalidElementId)
                                {
                                    solidOptions.MaterialId = overrideMaterialId;
                                }
                                extrusionObject = GeometryCreationUtilities.CreateExtrusionGeometry(loops, scaledExtrusionDirection, currDepth, solidOptions);
                            }
                            else
                            {
                                foreach (GeometryObject extrusionLayer in extrusionLayers)
                                {
                                    extrusions.Add(extrusionLayer);
                                }
                            }
                        }
                        else if (shapeEditScope.Creator.MaterialSelect is IFCMaterialProfileSetUsage)
                        {
                            extrusionObject = CreateGeometryFromMaterialProfile(shapeEditScope, loops, scaledExtrusionDirection, currDepth, solidOptions, out shouldWarn);
                            if (extrusionObject == null)
                            {
                                extrusionObject = GeometryCreationUtilities.CreateExtrusionGeometry(loops, scaledExtrusionDirection, currDepth, solidOptions);
                            }
                        }
                        else
                        {
                            extrusionObject = GeometryCreationUtilities.CreateExtrusionGeometry(loops, scaledExtrusionDirection, currDepth, solidOptions);
                        }
                    }
                    else
                    {
                        extrusionObject = GeometryCreationUtilities.CreateExtrusionGeometry(loops, scaledExtrusionDirection, currDepth, solidOptions);
                    }
                }
                catch (Exception ex)
                {
                    extrusionObject = GetMeshBackup(shapeEditScope, loops, scaledExtrusionDirection, currDepth);
                    if (extrusionObject == null)
                    {
                        throw ex;
                    }
                }

                if (extrusionObject != null)
                {
                    if (!(extrusionObject is Solid) || IFCGeometryUtil.ValidateGeometry(extrusionObject as Solid))
                    {
                        extrusions.Add(extrusionObject);
                    }
                    else
                    {
                        Mesh meshBackup = GetMeshBackup(shapeEditScope, loops, scaledExtrusionDirection, currDepth);
                        if (meshBackup != null)
                        {
                            extrusions.Add(meshBackup);
                        }
                    }
                }
            }

            return(extrusions);
        }
      // 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 ||
                !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;
      }
        /// <summary>
        /// Return geometry for a particular representation item.
        /// </summary>
        /// <param name="shapeEditScope">The shape edit scope.</param>
        /// <param name="lcs">Local coordinate system for the geometry.</param>
        /// <param name="guid">The guid of an element for which represntation is being created.</param>
        /// <returns>One or more created geometries.</returns>
        /// <remarks>The scaledLcs is only partially supported in this routine; it allows scaling the depth of the extrusion,
        /// which is commonly found in ACA files.</remarks>
        protected override IList <GeometryObject> CreateGeometryInternal(
            IFCImportShapeEditScope shapeEditScope, Transform lcs, Transform scaledLcs, string guid)
        {
            if (Direction == null)
            {
                Importer.TheLog.LogError(Id, "Error processing IfcExtrudedAreaSolid, can't create geometry.", false);
                return(null);
            }

            Transform origLCS       = (lcs == null) ? Transform.Identity : lcs;
            Transform origScaledLCS = (scaledLcs == null) ? Transform.Identity : scaledLcs;

            Transform extrusionPosition       = (Position == null) ? origLCS : origLCS.Multiply(Position);
            Transform scaledExtrusionPosition = (Position == null) ? origScaledLCS : origScaledLCS.Multiply(Position);

            XYZ extrusionDirection = extrusionPosition.OfVector(Direction);

            ISet <IList <CurveLoop> > disjointLoops = GetTransformedCurveLoops(extrusionPosition);

            if (disjointLoops == null || disjointLoops.Count() == 0)
            {
                return(null);
            }

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

            foreach (IList <CurveLoop> loops in disjointLoops)
            {
                SolidOptions solidOptions    = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
                XYZ          scaledDirection = scaledExtrusionPosition.OfVector(Direction);
                double       currDepth       = Depth * scaledDirection.GetLength();

                GeometryObject extrusionObject = null;
                try
                {
                    // We may try to create separate extrusions, one per layer here.
                    bool      shouldWarn                   = false;
                    ElementId overrideMaterialId           = ElementId.InvalidElementId;
                    IList <GeometryObject> extrusionLayers = CreateGeometryFromMaterialLayerUsage(shapeEditScope, extrusionPosition, loops,
                                                                                                  extrusionDirection, currDepth, out overrideMaterialId, out shouldWarn);

                    if (extrusionLayers == null || extrusionLayers.Count == 0)
                    {
                        if (shouldWarn)
                        {
                            Importer.TheLog.LogWarning(Id, "Couldn't process associated IfcMaterialLayerSetUsage, using body geometry instead.", false);
                        }
                        if (overrideMaterialId != ElementId.InvalidElementId)
                        {
                            solidOptions.MaterialId = overrideMaterialId;
                        }
                        extrusionObject = GeometryCreationUtilities.CreateExtrusionGeometry(loops, extrusionDirection, currDepth, solidOptions);
                    }
                    else
                    {
                        foreach (GeometryObject extrusionLayer in extrusionLayers)
                        {
                            extrusions.Add(extrusionLayer);
                        }
                    }
                }
                catch (Exception ex)
                {
                    if (shapeEditScope.MustCreateSolid())
                    {
                        throw ex;
                    }

                    Importer.TheLog.LogError(Id, "Extrusion has an invalid definition for a solid; reverting to mesh.", false);

                    MeshFromGeometryOperationResult meshResult = TessellatedShapeBuilder.CreateMeshByExtrusion(
                        loops, extrusionDirection, currDepth, GetMaterialElementId(shapeEditScope));

                    // will throw if mesh is not available
                    extrusionObject = meshResult.GetMesh();
                }

                if (extrusionObject != null)
                {
                    extrusions.Add(extrusionObject);
                }
            }

            return(extrusions);
        }
        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>
        /// 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 trimmedDirectrixInWCS = IFCGeometryUtil.CreateTransformed(trimmedDirectrix, sweptDiskPosition);

           // Create the disk.
           Curve firstCurve = null;
           foreach (Curve curve in trimmedDirectrixInWCS)
           {
              firstCurve = curve;
              break;
           }

           double startParam = 0.0;
           IList<CurveLoop> profileCurveLoops = CreateProfileCurveLoopsForDirectrix(firstCurve, out startParam);
           if (profileCurveLoops == null)
              return null;

           SolidOptions solidOptions = new SolidOptions(GetMaterialElementId(shapeEditScope), shapeEditScope.GraphicsStyleId);
           IList<GeometryObject> myObjs = new List<GeometryObject>();
           
           try
           {
              Solid sweptDiskSolid = GeometryCreationUtilities.CreateSweptGeometry(trimmedDirectrixInWCS, 0, startParam, profileCurveLoops,
                 solidOptions);
              if (sweptDiskSolid != null)
                 myObjs.Add(sweptDiskSolid);
           }
           catch (Exception ex)
           {
              // If we can't create a solid, we will attempt to split the Solid into valid pieces (that will likely have some overlap).
              if (ex.Message.Contains("self-intersections"))
              {
                 Importer.TheLog.LogWarning(Id, "The IfcSweptDiskSolid definition does not define a valid solid, likely due to self-intersections or other such problems; the profile probably extends too far toward the inner curvature of the sweep path. Creating the minimum number of solids possible to represent the geometry.", false);
                 myObjs = SplitSweptDiskIntoValidPieces(trimmedDirectrixInWCS, profileCurveLoops, solidOptions);
              }
              else
                 throw ex;
           }

           return myObjs;
        }
      /// <summary>
      /// Return a solid corresponding to the volume represented by boundingBoxXYZ. 
      /// </summary>
      /// <param name="lcs">The local coordinate system of the bounding box; if null, assume the Identity transform.</param>
      /// <param name="boundingBoxXYZ">The bounding box.</param>
      /// <param name="solidOptions">The options for creating the solid.  Allow null to mean default.</param>
      /// <returns>A solid of the same size and orientation as boundingBoxXYZ, or null if boundingBoxXYZ is invalid or null.</returns>
      /// <remarks>We don't do any checking on the input transform, which could have non-uniform scaling and/or mirroring.
      /// This could potentially lead to unexpected results, which we can examine if and when such cases arise.</remarks>
      public static Solid CreateSolidFromBoundingBox(Transform lcs, BoundingBoxXYZ boundingBoxXYZ, SolidOptions solidOptions)
      {
         // Check that the bounding box is valid.
         if (boundingBoxXYZ == null || !boundingBoxXYZ.Enabled)
            return null;

         try
         {
            // Create a transform based on the incoming local coordinate system and the bounding box coordinate system.
            Transform bboxTransform = (lcs == null) ? boundingBoxXYZ.Transform : lcs.Multiply(boundingBoxXYZ.Transform);

            XYZ[] profilePts = new XYZ[4];
            profilePts[0] = bboxTransform.OfPoint(boundingBoxXYZ.Min);
            profilePts[1] = bboxTransform.OfPoint(new XYZ(boundingBoxXYZ.Max.X, boundingBoxXYZ.Min.Y, boundingBoxXYZ.Min.Z));
            profilePts[2] = bboxTransform.OfPoint(new XYZ(boundingBoxXYZ.Max.X, boundingBoxXYZ.Max.Y, boundingBoxXYZ.Min.Z));
            profilePts[3] = bboxTransform.OfPoint(new XYZ(boundingBoxXYZ.Min.X, boundingBoxXYZ.Max.Y, boundingBoxXYZ.Min.Z));

            XYZ upperRightXYZ = bboxTransform.OfPoint(boundingBoxXYZ.Max);

            // If we assumed that the transforms had no scaling, 
            // then we could simply take boundingBoxXYZ.Max.Z - boundingBoxXYZ.Min.Z.
            // This code removes that assumption.
            XYZ origExtrusionVector = new XYZ(boundingBoxXYZ.Min.X, boundingBoxXYZ.Min.Y, boundingBoxXYZ.Max.Z) - boundingBoxXYZ.Min;
            XYZ extrusionVector = bboxTransform.OfVector(origExtrusionVector);

            double extrusionDistance = extrusionVector.GetLength();
            XYZ extrusionDirection = extrusionVector.Normalize();

            CurveLoop baseLoop = new CurveLoop();

            for (int ii = 0; ii < 4; ii++)
            {
               baseLoop.Append(Line.CreateBound(profilePts[ii], profilePts[(ii + 1) % 4]));
            }

            IList<CurveLoop> baseLoops = new List<CurveLoop>();
            baseLoops.Add(baseLoop);

            if (solidOptions == null)
               return GeometryCreationUtilities.CreateExtrusionGeometry(baseLoops, extrusionDirection, extrusionDistance);
            else
               return GeometryCreationUtilities.CreateExtrusionGeometry(baseLoops, extrusionDirection, extrusionDistance, solidOptions);
         }
         catch
         {
            return null;
         }
      }
        /// <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);
            }
        }
Example #42
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;
        }