Example #1
0
        /// <summary>
        /// Does this ray intersect with the provided GeometricElement? Only GeometricElements with Solid Representations are currently supported, and voids will be ignored.
        /// </summary>
        /// <param name="element">The element to intersect with.</param>
        /// <param name="result">The list of intersection results.</param>
        /// <returns></returns>
        public bool Intersects(GeometricElement element, out List <Vector3> result)
        {
            if (element.Representation == null || element.Representation.SolidOperations == null || element.Representation.SolidOperations.Count == 0)
            {
                element.UpdateRepresentations();
            }
            List <Vector3> resultsOut           = new List <Vector3>();
            var            transformFromElement = new Transform(element.Transform);

            transformFromElement.Invert();
            var transformToElement = new Transform(element.Transform);
            var transformedRay     = new Ray(transformFromElement.OfPoint(Origin), transformFromElement.OfVector(Direction));
            //TODO: extend to handle voids when void solids in Representations are supported generally
            var intersects = false;

            foreach (var solidOp in element.Representation.SolidOperations.Where(e => !e.IsVoid))
            {
                if (transformedRay.Intersects(solidOp, out List <Vector3> tempResults))
                {
                    intersects = true;
                    resultsOut.AddRange(tempResults.Select(t => transformToElement.OfPoint(t)));
                }
                ;
            }
            result = resultsOut;
            return(intersects);
        }
        internal static List <IfcProduct> ToIfcProducts(this Element e,
                                                        IfcRepresentationContext context,
                                                        Document doc,
                                                        Dictionary <Guid, List <IfcStyleAssignmentSelect> > styleAssignments)
        {
            var products = new List <IfcProduct>();

            IfcProductDefinitionShape shape      = null;
            GeometricElement          geoElement = null;
            Transform trans = null;
            Guid      id    = default(Guid);

            if (e is ElementInstance)
            {
                // If we're using an element instance, get the transform
                // and the id and use those to uniquely position and
                // identify the element.
                var instance = (ElementInstance)e;
                geoElement = instance.BaseDefinition;
                id         = instance.Id;
                trans      = instance.Transform;
            }
            else if (e is GeometricElement)
            {
                // If we've go a geometric element, use its properties as-is.
                geoElement = (GeometricElement)e;
                id         = geoElement.Id;
                trans      = geoElement.Transform;
            }

            geoElement.UpdateRepresentations();

            var localPlacement = trans.ToIfcLocalPlacement(doc);

            doc.AddEntity(localPlacement);

            var geoms = new List <IfcRepresentationItem>();

            if (geoElement is MeshElement)
            {
                var meshEl  = (MeshElement)geoElement;
                var lengths = meshEl.Mesh.Vertices.Select(v => v.Position.ToArray().Select(vi => new IfcLengthMeasure(vi)).ToList()).ToList();
                var pts     = new IfcCartesianPointList3D(lengths);
                doc.AddEntity(pts);
                var indices = meshEl.Mesh.Triangles.Select(t => t.Vertices.Select(vx => new IfcPositiveInteger(vx.Index + 1)).ToList()).ToList();
                var idxs    = new List <List <IfcPositiveInteger> >(indices);
                var geom    = new IfcTriangulatedFaceSet(pts, indices);
                geom.Closed = false;
                doc.AddEntity(geom);
                geoms.Add(geom);
                shape = ToIfcProductDefinitionShape(geoms, "Tessellation", context, doc);
            }
            else
            {
                foreach (var op in geoElement.Representation.SolidOperations)
                {
                    if (op is Sweep)
                    {
                        var sweep = (Sweep)op;

                        // Neither of these entities, which are part of the
                        // IFC4 specification, and which would allow a sweep
                        // along a curve, are supported by many applications
                        // which are supposedly IFC4 compliant (Revit). For
                        // Those applications where these entities appear,
                        // the rotation of the profile is often wrong or
                        // inconsistent.
                        // geom = sweep.ToIfcSurfaceCurveSweptAreaSolid(doc);
                        // geom = sweep.ToIfcFixedReferenceSweptAreaSolid(geoElement.Transform, doc);

                        // Instead, we'll divide the curve and create a set of
                        // linear extrusions instead.
                        Polyline pline;
                        if (sweep.Curve is Line)
                        {
                            pline = sweep.Curve.ToPolyline(1);
                        }
                        else
                        {
                            pline = sweep.Curve.ToPolyline();
                        }
                        foreach (var segment in pline.Segments())
                        {
                            var position         = segment.TransformAt(0.0).ToIfcAxis2Placement3D(doc);
                            var extrudeDepth     = segment.Length();
                            var extrudeProfile   = sweep.Profile.Perimeter.ToIfcArbitraryClosedProfileDef(doc);
                            var extrudeDirection = Vector3.ZAxis.Negate().ToIfcDirection();
                            var geom             = new IfcExtrudedAreaSolid(extrudeProfile, position,
                                                                            extrudeDirection, new IfcPositiveLengthMeasure(extrudeDepth));

                            doc.AddEntity(extrudeProfile);
                            doc.AddEntity(extrudeDirection);
                            doc.AddEntity(position);
                            doc.AddEntity(geom);
                            geoms.Add(geom);
                        }
                    }
                    else if (op is Extrude)
                    {
                        var extrude = (Extrude)op;
                        var geom    = extrude.ToIfcExtrudedAreaSolid(doc);
                        doc.AddEntity(geom);
                        geoms.Add(geom);
                    }
                    else if (op is Lamina)
                    {
                        var lamina = (Lamina)op;
                        var geom   = lamina.ToIfcShellBasedSurfaceModel(doc);
                        doc.AddEntity(geom);
                        geoms.Add(geom);
                    }
                    else
                    {
                        throw new Exception("Only IExtrude, ISweepAlongCurve, and ILamina representations are currently supported.");
                    }
                }
                shape = ToIfcProductDefinitionShape(geoms, "SolidModel", context, doc);
            }
            doc.AddEntity(shape);


            // Can we use IfcMappedItem?
            // https://forums.buildingsmart.org/t/can-tessellation-typed-representation-hold-items-from-another-group/1621
            // var rep = new IfcShapeRepresentation(context, "Body", "Solids", geoms);
            // doc.AddEntity(rep);
            // var axisPt = Vector3.Origin.ToIfcCartesianPoint();
            // doc.AddEntity(axisPt);
            // var axis = new IfcAxis2Placement2D(axisPt);
            // doc.AddEntity(axis);
            // var repMap = new IfcRepresentationMap(new IfcAxis2Placement(axis), rep);
            // doc.AddEntity(repMap);
            // var x = trans.XAxis.ToIfcDirection();
            // var y = trans.YAxis.ToIfcDirection();
            // var z = trans.ZAxis.ToIfcDirection();
            // var origin = trans.Origin.ToIfcCartesianPoint();
            // var cart = new IfcCartesianTransformationOperator3D(x, y, origin, trans.XAxis.Length(), z);
            // doc.AddEntity(x);
            // doc.AddEntity(y);
            // doc.AddEntity(z);
            // doc.AddEntity(origin);
            // doc.AddEntity(cart);
            // var mappedItem = new IfcMappedItem(repMap, cart);
            // doc.AddEntity(mappedItem);
            // var shapeRep= new IfcShapeRepresentation(context, new List<IfcRepresentationItem>(){mappedItem});
            // doc.AddEntity(shapeRep);
            // shape = new IfcProductDefinitionShape(new List<IfcRepresentation>(){shapeRep});
            // doc.AddEntity(shape);

            var product = ConvertElementToIfcProduct(id, geoElement, localPlacement, shape);

            products.Add(product);
            doc.AddEntity(product);

            var ifcOpenings = doc.AllEntities.Where(ent => ent.GetType() == typeof(IfcOpeningElement)).Cast <IfcOpeningElement>();

            // If the element has openings, make opening relationships in
            // the IfcElement.
            if (e is IHasOpenings)
            {
                var openings = (IHasOpenings)e;
                if (openings.Openings.Count > 0)
                {
                    foreach (var o in openings.Openings)
                    {
                        var element = (IfcElement)product;
                        // TODO: Find the opening that we've already created that relates here
                        var opening = ifcOpenings.First(ifcO => ifcO.GlobalId == IfcGuid.ToIfcGuid(o.Id));
                        var voidRel = new IfcRelVoidsElement(IfcGuid.ToIfcGuid(Guid.NewGuid()), element, opening);
                        element.HasOpenings.Add(voidRel);
                        doc.AddEntity(voidRel);
                    }
                }
            }

            foreach (var geom in geoms)
            {
                var styledItem = new IfcStyledItem(geom, styleAssignments[geoElement.Material.Id], null);
                doc.AddEntity(styledItem);
            }

            return(products);
        }
Example #3
0
        public void UnionWithProblematicPolygons()
        {
            var profile1 = JsonConvert.DeserializeObject <Polygon>(
                @"{
                ""Vertices"": [
                    {
                        ""X"": -348.82036858497275,
                        ""Y"": 246.02759072077453,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -348.85572392403208,
                        ""Y"": 246.06294605983385,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -350.60244308413706,
                        ""Y"": 244.31622689972886,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -350.56708774507774,
                        ""Y"": 244.28087156066954,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -350.53173240601842,
                        ""Y"": 244.24551622161022,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -348.78501324591343,
                        ""Y"": 245.9922353817152,
                        ""Z"": 30.25
                    }
                ]}
                ");
            var profile2 = JsonConvert.DeserializeObject <Polygon>(
                @"{
                ""Vertices"": [
                    {
                        ""X"": -350.56708774507774,
                        ""Y"": 244.28087156066954,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -350.51708774507773,
                        ""Y"": 244.28087156066954,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -350.51708774507773,
                        ""Y"": 247.77430988087954,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -350.56708774507774,
                        ""Y"": 247.77430988087954,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -350.61708774507775,
                        ""Y"": 247.77430988087954,
                        ""Z"": 30.25
                    },
                    {
                        ""X"": -350.61708774507775,
                        ""Y"": 244.28087156066954,
                        ""Z"": 30.25
                    }
                    ]}"
                );
            var element = new GeometricElement();

            element.Representation = new Representation(new List <SolidOperation> {
                new Extrude(profile1, 1, Vector3.ZAxis, false),
                new Extrude(profile2, 1, Vector3.ZAxis, false)
            });

            element.UpdateRepresentations();
            var solid = element.GetFinalCsgFromSolids();
        }