Esempio n. 1
0
        override protected void Process(IFCAnyHandle ifcGeometricSet)
        {
            base.Process(ifcGeometricSet);

            IList <IFCAnyHandle> elements = IFCAnyHandleUtil.GetAggregateInstanceAttribute <List <IFCAnyHandle> >(ifcGeometricSet, "Elements");

            if (elements != null)
            {
                foreach (IFCAnyHandle element in elements)
                {
                    if (IFCAnyHandleUtil.IsSubTypeOf(element, IFCEntityType.IfcCurve))
                    {
                        IFCCurve curve = IFCCurve.ProcessIFCCurve(element);
                        if (curve != null)
                        {
                            Curves.Add(curve);
                        }
                    }
                    else
                    {
                        Importer.TheLog.LogError(Id, "Unhandled entity type in IfcGeometricSet: " + IFCAnyHandleUtil.GetEntityType(element).ToString(), false);
                    }
                }
            }
        }
        override protected void Process(IFCAnyHandle solid)
        {
            base.Process(solid);

            IFCAnyHandle directrix = IFCImportHandleUtil.GetRequiredInstanceAttribute(solid, "Directrix", true);

            Directrix = IFCCurve.ProcessIFCCurve(directrix);

            IFCAnyHandle referenceSurface = IFCImportHandleUtil.GetRequiredInstanceAttribute(solid, "ReferenceSurface", true);

            ReferenceSurface = IFCSurface.ProcessIFCSurface(referenceSurface);

            StartParameter = IFCImportHandleUtil.GetOptionalDoubleAttribute(solid, "StartParam", 0.0);
            if (StartParameter < MathUtil.Eps())
            {
                StartParameter = 0.0;
            }

            double endParameter = IFCImportHandleUtil.GetOptionalDoubleAttribute(solid, "EndParam", -1.0);

            if (!MathUtil.IsAlmostEqual(endParameter, -1.0))
            {
                if (endParameter < StartParameter + MathUtil.Eps())
                {
                    Importer.TheLog.LogError(solid.StepId, "IfcSurfaceCurveSweptAreaSolid swept curve end parameter less than or equal to start parameter, aborting.", true);
                }
                EndParameter = endParameter;
            }
        }
Esempio n. 3
0
        private double?GetTrimParameter(IFCData trim, IFCCurve basisCurve, IFCTrimmingPreference trimPreference, bool secondAttempt)
        {
            bool preferParam = !(trimPreference == IFCTrimmingPreference.Cartesian);

            if (secondAttempt)
            {
                preferParam = !preferParam;
            }
            double vertexEps = MathUtil.VertexEps;

            IFCAggregate trimAggregate = trim.AsAggregate();

            foreach (IFCData trimParam in trimAggregate)
            {
                if (!preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Instance))
                {
                    IFCAnyHandle trimParamInstance = trimParam.AsInstance();
                    XYZ          trimParamPt       = IFCPoint.ProcessScaledLengthIFCCartesianPoint(trimParamInstance);
                    if (trimParamPt == null)
                    {
                        IFCImportFile.TheLog.LogWarning(basisCurve.Id, "Invalid trim point for basis curve.", false);
                        continue;
                    }

                    try
                    {
                        IntersectionResult result = basisCurve.Curve.Project(trimParamPt);
                        if (result.Distance < vertexEps)
                        {
                            return(result.Parameter);
                        }

                        IFCImportFile.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false);
                    }
                    catch
                    {
                        IFCImportFile.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false);
                    }
                }
                else if (preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Double))
                {
                    double trimParamDouble = trimParam.AsDouble();
                    if (basisCurve.Curve.IsCyclic)
                    {
                        trimParamDouble = IFCUnitUtil.ScaleAngle(trimParamDouble);
                    }
                    return(trimParamDouble);
                }
            }

            // Try again with opposite preference.
            if (!secondAttempt)
            {
                return(GetTrimParameter(trim, basisCurve, trimPreference, true));
            }

            return(null);
        }
Esempio n. 4
0
        private void ProcessIFCCompositeCurveSegment(IFCAnyHandle ifcCurveSegment)
        {
            bool found = false;

            bool sameSense = IFCImportHandleUtil.GetRequiredBooleanAttribute(ifcCurveSegment, "SameSense", out found);

            if (!found)
            {
                sameSense = true;
            }

            IFCAnyHandle parentCurve    = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurveSegment, "ParentCurve", true);
            IFCCurve     ifcParentCurve = IFCCurve.ProcessIFCCurve(parentCurve);

            if (ifcParentCurve == null)
            {
                IFCImportFile.TheLog.LogError(ifcCurveSegment.StepId, "Error processing ParentCurve for IfcCompositeCurveSegment.", false);
                return;
            }

            bool hasCurve     = (ifcParentCurve.Curve != null);
            bool hasCurveLoop = (ifcParentCurve.CurveLoop != null);

            if (!hasCurve && !hasCurveLoop)
            {
                IFCImportFile.TheLog.LogError(ifcCurveSegment.StepId, "Error processing ParentCurve for IfcCompositeCurveSegment.", false);
                return;
            }
            else
            {
                // The CurveLoop here is from the parent IfcCurve, which is the IfcCompositeCurve, which will correspond to a CurveLoop.
                // IfcCompositiveCurveSegment may be either a curve or a curveloop, which we want to append to the parent curveloop.
                if (CurveLoop == null)
                {
                    CurveLoop = new CurveLoop();
                }
            }

            try
            {
                if (hasCurve)
                {
                    AddCurveToLoop(CurveLoop, ifcParentCurve.Curve, !sameSense, true);
                }
                else if (hasCurveLoop)
                {
                    foreach (Curve subCurve in ifcParentCurve.CurveLoop)
                    {
                        AddCurveToLoop(CurveLoop, subCurve, !sameSense, true);
                    }
                }
            }
            catch (Exception ex)
            {
                IFCImportFile.TheLog.LogError(ifcParentCurve.Id, ex.Message, true);
            }
        }
Esempio n. 5
0
        /// <summary>
        /// Get the curve from the Axis representation of the given IfcProduct, transformed to the current local coordinate system.
        /// </summary>
        /// <param name="creator">The IfcProduct that may or may not contain a valid axis curve.</param>
        /// <param name="lcs">The local coordinate system.</param>
        /// <returns>The axis curve, if found, and valid.</returns>
        /// <remarks>In this case, we only allow bounded curves to be valid axis curves.
        /// The Curve may be contained as either a single Curve in the IFCCurve representation item,
        /// or it could be an open CurveLoop that could be represented as a single curve.</remarks>
        private Curve GetAxisCurve(IFCProduct creator, Transform lcs)
        {
            // We need an axis curve to clip the extrusion profiles; if we can't get one, fail
            IFCProductRepresentation productRepresentation = creator.ProductRepresentation;

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

            IList <IFCRepresentation> representations = productRepresentation.Representations;

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

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

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

                // Go through the list of representation items in the Axis representation, to look for the IfcCurve.
                foreach (IFCRepresentationItem item in items)
                {
                    if (item is IFCCurve)
                    {
                        // We will accept a bounded curve, or an open CurveLoop that can be represented
                        // as one curve.
                        IFCCurve ifcCurve  = item as IFCCurve;
                        Curve    axisCurve = ifcCurve.Curve;
                        if (axisCurve == null)
                        {
                            axisCurve = ifcCurve.ConvertCurveLoopIntoSingleCurve();
                        }

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

            return(null);
        }
Esempio n. 6
0
        /// <summary>
        /// Processes an IfcRepresentationItem entity handle.
        /// </summary>
        /// <param name="ifcRepresentationItem">The IfcRepresentationItem handle.</param>
        /// <returns>The IFCRepresentationItem object.</returns>
        public static IFCRepresentationItem ProcessIFCRepresentationItem(IFCAnyHandle ifcRepresentationItem)
        {
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcBooleanResult))
            {
                return(IFCBooleanResult.ProcessIFCBooleanResult(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcCurve))
            {
                return(IFCCurve.ProcessIFCCurve(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcFaceBasedSurfaceModel))
            {
                return(IFCFaceBasedSurfaceModel.ProcessIFCFaceBasedSurfaceModel(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcGeometricSet))
            {
                return(IFCGeometricSet.ProcessIFCGeometricSet(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcMappedItem))
            {
                return(IFCMappedItem.ProcessIFCMappedItem(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcShellBasedSurfaceModel))
            {
                return(IFCShellBasedSurfaceModel.ProcessIFCShellBasedSurfaceModel(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcSolidModel))
            {
                return(IFCSolidModel.ProcessIFCSolidModel(ifcRepresentationItem));
            }

            if (IFCImportFile.TheFile.SchemaVersion >= IFCSchemaVersion.IFC2x2 && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcStyledItem))
            {
                return(IFCStyledItem.ProcessIFCStyledItem(ifcRepresentationItem));
            }

            if (IFCImportFile.TheFile.SchemaVersion >= IFCSchemaVersion.IFC4 && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcTriangulatedFaceSet))
            {
                return(IFCTriangulatedFaceSet.ProcessIFCTriangulatedFaceSet(ifcRepresentationItem));
            }

            if (IFCImportFile.TheFile.SchemaVersion >= IFCSchemaVersion.IFC4Add2 && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcPolygonalFaceSet))
            {
                return(IFCPolygonalFaceSet.ProcessIFCPolygonalFaceSet(ifcRepresentationItem));
            }

            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcTopologicalRepresentationItem))
            {
                return(IFCTopologicalRepresentationItem.ProcessIFCTopologicalRepresentationItem(ifcRepresentationItem));
            }

            Importer.TheLog.LogUnhandledSubTypeError(ifcRepresentationItem, IFCEntityType.IfcRepresentationItem, true);
            return(null);
        }
        private IList <Curve> ProcessIFCCompositeCurveSegment(IFCAnyHandle ifcCurveSegment)
        {
            bool found = false;

            bool sameSense = IFCImportHandleUtil.GetRequiredBooleanAttribute(ifcCurveSegment, "SameSense", out found);

            if (!found)
            {
                sameSense = true;
            }

            IFCAnyHandle ifcParentCurve = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurveSegment, "ParentCurve", true);
            IFCCurve     parentCurve    = null;

            using (TemporaryVerboseLogging logger = new TemporaryVerboseLogging())
            {
                parentCurve = IFCCurve.ProcessIFCCurve(ifcParentCurve);
            }

            if (parentCurve == null)
            {
                Importer.TheLog.LogWarning(ifcCurveSegment.StepId, "Error processing ParentCurve (#" + ifcParentCurve.StepId + ") for IfcCompositeCurveSegment; this may be repairable.", false);
                return(null);
            }

            bool hasCurve     = (parentCurve.Curve != null);
            bool hasCurveLoop = (parentCurve.CurveLoop != null);

            if (!hasCurve && !hasCurveLoop)
            {
                Importer.TheLog.LogWarning(ifcCurveSegment.StepId, "Error processing ParentCurve (#" + ifcParentCurve.StepId + ") for IfcCompositeCurveSegment; this may be repairable.", false);
                return(null);
            }

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

            if (hasCurve)
            {
                curveSegments.Add(parentCurve.Curve);
            }
            else if (hasCurveLoop)
            {
                foreach (Curve subCurve in parentCurve.CurveLoop)
                {
                    curveSegments.Add(subCurve);
                }
            }

            return(curveSegments);
        }
Esempio n. 8
0
        override protected void Process(IFCAnyHandle solid)
        {
            base.Process(solid);

            IFCAnyHandle directrix = IFCImportHandleUtil.GetRequiredInstanceAttribute(solid, "Directrix", true);

            Directrix = IFCCurve.ProcessIFCCurve(directrix);

            bool found = false;

            Radius = IFCImportHandleUtil.GetRequiredScaledLengthAttribute(solid, "Radius", out found);
            if (!found || !Application.IsValidThickness(Radius))
            {
                Importer.TheLog.LogError(solid.StepId, "IfcSweptDiskSolid radius is invalid, aborting.", true);
            }

            double innerRadius = IFCImportHandleUtil.GetOptionalScaledLengthAttribute(solid, "InnerRadius", 0.0);

            if (Application.IsValidThickness(innerRadius))
            {
                if (!Application.IsValidThickness(Radius - innerRadius))
                {
                    Importer.TheLog.LogError(solid.StepId, "IfcSweptDiskSolid inner radius is too large, aborting.", true);
                }
                InnerRadius = innerRadius;
            }

            StartParameter = IFCImportHandleUtil.GetOptionalDoubleAttribute(solid, "StartParam", 0.0);
            if (StartParameter < MathUtil.Eps())
            {
                StartParameter = 0.0;
            }

            double endParameter = IFCImportHandleUtil.GetOptionalDoubleAttribute(solid, "EndParam", -1.0);

            if (!MathUtil.IsAlmostEqual(endParameter, -1.0))
            {
                if (endParameter < StartParameter + MathUtil.Eps())
                {
                    Importer.TheLog.LogWarning(solid.StepId, "IfcSweptDiskSolid swept curve end parameter less than or equal to start parameter, ignoring both.", true);
                    StartParameter = 0.0;
                }
                else
                {
                    EndParameter = endParameter;
                }
            }
        }
Esempio n. 9
0
        /// <summary>
        /// Create an IFCCurve object from a handle of type IfcCurve.
        /// </summary>
        /// <param name="ifcCurve">The IFC handle.</param>
        /// <returns>The IFCCurve object.</returns>
        public static IFCCurve ProcessIFCCurve(IFCAnyHandle ifcCurve)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcCurve))
            {
                IFCImportFile.TheLog.LogNullError(IFCEntityType.IfcCurve);
                return(null);
            }

            IFCEntity curve;

            if (!IFCImportFile.TheFile.EntityMap.TryGetValue(ifcCurve.StepId, out curve))
            {
                curve = new IFCCurve(ifcCurve);
            }
            return(curve as IFCCurve);
        }
        protected override void Process(IFCAnyHandle ifcEdgeCurve)
        {
            base.Process(ifcEdgeCurve);
            IFCAnyHandle edgeGeometry = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcEdgeCurve, "EdgeGeometry", true);
            EdgeGeometry = IFCCurve.ProcessIFCCurve(edgeGeometry);

            bool found = false;
            bool sameSense = IFCImportHandleUtil.GetRequiredBooleanAttribute(ifcEdgeCurve, "SameSense", out found);
            if (found)
                SameSense = sameSense;
            else
            {
                Importer.TheLog.LogWarning(ifcEdgeCurve.StepId, "Cannot find SameSense attribute, defaulting to true", false);
                SameSense = true;
            }
        }
Esempio n. 11
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            IFCAnyHandle basisCurve = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurve, "BasisCurve", false);

            if (basisCurve == null)
            {
                return;
            }

            IFCAnyHandle dir = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurve, "RefDirection", false);

            bool   found    = false;
            double distance = IFCImportHandleUtil.GetRequiredScaledLengthAttribute(ifcCurve, "Distance", out found);

            if (!found)
            {
                distance = 0.0;
            }

            IFCCurve ifcBasisCurve = IFCCurve.ProcessIFCCurve(basisCurve);
            XYZ      dirXYZ        = (dir == null) ? ifcBasisCurve.GetNormal() : IFCPoint.ProcessNormalizedIFCDirection(dir);

            try
            {
                if (ifcBasisCurve.Curve != null)
                {
                    SetCurve(ifcBasisCurve.Curve.CreateOffset(distance, XYZ.BasisZ));
                }
                else
                {
                    CurveLoop baseCurveLoop = ifcBasisCurve.GetTheCurveLoop();
                    if (baseCurveLoop != null)
                    {
                        SetCurveLoop(CurveLoop.CreateViaOffset(baseCurveLoop, distance, XYZ.BasisZ));
                    }
                }
            }
            catch
            {
                Importer.TheLog.LogError(ifcCurve.StepId, "Couldn't create offset curve.", false);
            }
        }
Esempio n. 12
0
        private void GetTrimParameters(IFCData trim1, IFCData trim2, IFCCurve basisCurve, IFCTrimmingPreference trimPreference,
                                       out double param1, out double param2)
        {
            double?condParam1 = GetTrimParameter(trim1, basisCurve, trimPreference, false);

            if (!condParam1.HasValue)
            {
                throw new InvalidOperationException("#" + basisCurve.Id + ": Couldn't apply first trimming parameter of IfcTrimmedCurve.");
            }
            param1 = condParam1.Value;

            double?condParam2 = GetTrimParameter(trim2, basisCurve, trimPreference, false);

            if (!condParam2.HasValue)
            {
                throw new InvalidOperationException("#" + basisCurve.Id + ": Couldn't apply second trimming parameter of IfcTrimmedCurve.");
            }
            param2 = condParam2.Value;

            if (MathUtil.IsAlmostEqual(param1, param2))
            {
                // If we had a cartesian parameter as the trim preference, check if the parameter values are better.
                if (trimPreference == IFCTrimmingPreference.Cartesian)
                {
                    condParam1 = GetTrimParameter(trim1, basisCurve, IFCTrimmingPreference.Parameter, true);
                    if (!condParam1.HasValue)
                    {
                        throw new InvalidOperationException("#" + basisCurve.Id + ": Couldn't apply first trimming parameter of IfcTrimmedCurve.");
                    }
                    param1 = condParam1.Value;

                    condParam2 = GetTrimParameter(trim2, basisCurve, IFCTrimmingPreference.Parameter, true);
                    if (!condParam2.HasValue)
                    {
                        throw new InvalidOperationException("#" + basisCurve.Id + ": Couldn't apply second trimming parameter of IfcTrimmedCurve.");
                    }
                    param2 = condParam2.Value;
                }
                else
                {
                    throw new InvalidOperationException("#" + basisCurve.Id + ": Ignoring 0 length curve.");
                }
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Processes an IfcRepresentationItem entity handle.
        /// </summary>
        /// <param name="ifcRepresentationItem">The IfcRepresentationItem handle.</param>
        /// <returns>The IFCRepresentationItem object.</returns>
        public static IFCRepresentationItem ProcessIFCRepresentationItem(IFCAnyHandle ifcRepresentationItem)
        {
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcBooleanResult))
            {
                return(IFCBooleanResult.ProcessIFCBooleanResult(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcConnectedFaceSet))
            {
                return(IFCConnectedFaceSet.ProcessIFCConnectedFaceSet(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcCurve))
            {
                return(IFCCurve.ProcessIFCCurve(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcFaceBasedSurfaceModel))
            {
                return(IFCFaceBasedSurfaceModel.ProcessIFCFaceBasedSurfaceModel(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcGeometricSet))
            {
                return(IFCGeometricSet.ProcessIFCGeometricSet(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcMappedItem))
            {
                return(IFCMappedItem.ProcessIFCMappedItem(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcShellBasedSurfaceModel))
            {
                return(IFCShellBasedSurfaceModel.ProcessIFCShellBasedSurfaceModel(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcSolidModel))
            {
                return(IFCSolidModel.ProcessIFCSolidModel(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcStyledItem))
            {
                return(IFCStyledItem.ProcessIFCStyledItem(ifcRepresentationItem));
            }

            IFCImportFile.TheLog.LogUnhandledSubTypeError(ifcRepresentationItem, IFCEntityType.IfcRepresentationItem, true);
            return(null);
        }
Esempio n. 14
0
        protected override void Process(IFCAnyHandle ifcEdgeCurve)
        {
            base.Process(ifcEdgeCurve);
            IFCAnyHandle edgeGeometry = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcEdgeCurve, "EdgeGeometry", true);

            EdgeGeometry = IFCCurve.ProcessIFCCurve(edgeGeometry);

            bool found     = false;
            bool sameSense = IFCImportHandleUtil.GetRequiredBooleanAttribute(ifcEdgeCurve, "SameSense", out found);

            if (found)
            {
                SameSense = sameSense;
            }
            else
            {
                Importer.TheLog.LogWarning(ifcEdgeCurve.StepId, "Cannot find SameSense attribute, defaulting to true", false);
                SameSense = true;
            }
        }
Esempio n. 15
0
        override protected void Process(IFCAnyHandle solid)
        {
            base.Process(solid);

            bool found         = false;
            bool agreementFlag = IFCImportHandleUtil.GetRequiredBooleanAttribute(solid, "AgreementFlag", out found);

            if (found)
            {
                AgreementFlag = agreementFlag;
            }

            IFCAnyHandle baseSurface = IFCImportHandleUtil.GetRequiredInstanceAttribute(solid, "BaseSurface", true);

            BaseSurface = IFCSurface.ProcessIFCSurface(baseSurface);
            if (!(BaseSurface is IFCPlane))
            {
                Importer.TheLog.LogUnhandledSubTypeError(baseSurface, IFCEntityType.IfcSurface, true);
            }

            if (IFCAnyHandleUtil.IsValidSubTypeOf(solid, IFCEntityType.IfcPolygonalBoundedHalfSpace))
            {
                IFCAnyHandle position = IFCImportHandleUtil.GetRequiredInstanceAttribute(solid, "Position", false);
                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(position))
                {
                    BaseBoundingCurveTransform = IFCLocation.ProcessIFCAxis2Placement(position);
                }
                else
                {
                    BaseBoundingCurveTransform = Transform.Identity;
                }

                IFCAnyHandle boundaryCurveHandle = IFCImportHandleUtil.GetRequiredInstanceAttribute(solid, "PolygonalBoundary", true);
                BaseBoundingCurve = IFCCurve.ProcessIFCCurve(boundaryCurveHandle);
                if (BaseBoundingCurve == null || BaseBoundingCurve.GetTheCurveLoop() == null)
                {
                    Importer.TheLog.LogError(Id, "IfcPolygonalBoundedHalfSpace has an invalid boundary, ignoring.", true);
                }
            }
        }
Esempio n. 16
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            IFCAnyHandle basisCurve = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurve, "BasisCurve", false);

            if (basisCurve == null)
            {
                return;
            }

            bool   found    = false;
            double distance = IFCImportHandleUtil.GetRequiredScaledLengthAttribute(ifcCurve, "Distance", out found);

            if (!found)
            {
                distance = 0.0;
            }

            try
            {
                IFCCurve ifcBasisCurve = IFCCurve.ProcessIFCCurve(basisCurve);
                if (ifcBasisCurve.Curve != null)
                {
                    Curve = ifcBasisCurve.Curve.CreateOffset(distance, XYZ.BasisZ);
                }
                else if (ifcBasisCurve.CurveLoop != null)
                {
                    CurveLoop = CurveLoop.CreateViaOffset(ifcBasisCurve.CurveLoop, distance, XYZ.BasisZ);
                }
            }
            catch
            {
                Importer.TheLog.LogError(ifcCurve.StepId, "Couldn't create offset curve.", false);
            }
        }
        /// <summary>
        /// Get the curve from the Axis representation of the given IfcProduct, transformed to the current local coordinate system.
        /// </summary>
        /// <param name="creator">The IfcProduct that may or may not contain a valid axis curve.</param>
        /// <param name="lcs">The local coordinate system.</param>
        /// <returns>The axis curve, if found, and valid.</returns>
        /// <remarks>In this case, we only allow bounded lines and arcs to be valid axis curves, as per IFC2x3 convention.
        /// The Curve may be contained as either a single Curve in the IFCCurve representation item, or it could be an
        /// open CurveLoop with one item.</remarks>
        private Curve GetAxisCurve(IFCProduct creator, Transform lcs)
        {
            // We need an axis curve to clip the extrusion profiles; if we can't get one, fail
            IFCProductRepresentation productRepresentation = creator.ProductRepresentation;

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

            IList <IFCRepresentation> representations = productRepresentation.Representations;

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

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

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

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

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

            return(null);
        }
Esempio n. 18
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            bool found = false;

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

            if (!found)
            {
                sameSense = true;
            }

            IFCAnyHandle basisCurve    = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurve, "BasisCurve", true);
            IFCCurve     ifcBasisCurve = IFCCurve.ProcessIFCCurve(basisCurve);

            if (ifcBasisCurve == null || (ifcBasisCurve.IsEmpty()))
            {
                // LOG: ERROR: Error processing BasisCurve # for IfcTrimmedCurve #.
                return;
            }
            if (ifcBasisCurve.Curve == null)
            {
                // LOG: ERROR: Expected a single curve, not a curve loop for BasisCurve # for IfcTrimmedCurve #.
                return;
            }

            IFCData trim1 = ifcCurve.GetAttribute("Trim1");

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

            IFCData trim2 = ifcCurve.GetAttribute("Trim2");

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

            // Note that these are the "unprocessed" values.  These can be used for, e.g., adding up the IFC parameter length
            // of the file, to account for export errors.  The "processed" values can be determined from the Revit curves.
            Trim1 = GetRawTrimParameter(trim1);
            Trim2 = GetRawTrimParameter(trim2);

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

            double param1 = 0.0, param2 = 0.0;
            Curve  baseCurve = ifcBasisCurve.Curve;

            try
            {
                GetTrimParameters(ifcBasisCurve.Id, trim1, trim2, baseCurve, trimPreference, out param1, out param2);
                if (NeedToReverseBaseCurve(baseCurve, param1, param2, trimPreference))
                {
                    Importer.TheLog.LogWarning(Id, "Invalid Param1 > Param2 for non-cyclic IfcTrimmedCurve using Cartesian trimming preference, reversing.", false);
                    baseCurve = baseCurve.CreateReversed();
                    GetTrimParameters(ifcBasisCurve.Id, trim1, trim2, baseCurve, trimPreference, out param1, out param2);
                }
            }
            catch (Exception ex)
            {
                Importer.TheLog.LogError(ifcCurve.StepId, ex.Message, false);
                return;
            }

            if (MathUtil.IsAlmostEqual(param1, param2))
            {
                Importer.TheLog.LogError(Id, "Param1 = Param2 for IfcTrimmedCurve #, ignoring.", false);
                return;
            }

            Curve curve = null;

            if (baseCurve.IsCyclic)
            {
                double period = baseCurve.Period;
                if (!sameSense)
                {
                    MathUtil.Swap(ref param1, ref param2);
                }

                // We want to make sure both values are within period of one another.
                param1 = MathUtil.PutInRange(param1, 0, period);
                param2 = MathUtil.PutInRange(param2, 0, period);
                if (param2 < param1)
                {
                    param2 = MathUtil.PutInRange(param2, param1 + period / 2, period);
                }

                // This is effectively an unbound curve.
                double numberOfPeriods = (param2 - param1) / period;
                if (MathUtil.IsAlmostEqual(numberOfPeriods, Math.Round(numberOfPeriods)))
                {
                    Importer.TheLog.LogWarning(Id, "Start and end parameters indicate a zero-length closed curve, assuming unbound is intended.", false);
                    curve = baseCurve;
                }
                else
                {
                    curve = baseCurve.Clone();
                    if (!SafelyBoundCurve(curve, param1, param2))
                    {
                        return;
                    }
                }
            }
            else
            {
                if (param1 > param2 - MathUtil.Eps())
                {
                    Importer.TheLog.LogWarning(Id, "Param1 > Param2 for IfcTrimmedCurve #, reversing.", false);
                    MathUtil.Swap(ref param1, ref param2);
                    sameSense = !sameSense;
                }

                Curve copyCurve = baseCurve.Clone();

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

                if (!SafelyBoundCurve(copyCurve, param1, param2))
                {
                    return;
                }

                if (sameSense)
                {
                    curve = copyCurve;
                }
                else
                {
                    curve = copyCurve.CreateReversed();
                }
            }

            CurveLoop curveLoop = new CurveLoop();

            curveLoop.Append(curve);
            SetCurveLoop(curveLoop);
        }
Esempio n. 19
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

            bool found = false;

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

            if (!found)
            {
                sameSense = true;
            }

            IFCAnyHandle basisCurve    = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurve, "BasisCurve", true);
            IFCCurve     ifcBasisCurve = IFCCurve.ProcessIFCCurve(basisCurve);

            if (ifcBasisCurve == null || (ifcBasisCurve.Curve == null && ifcBasisCurve.CurveLoop == null))
            {
                // LOG: ERROR: Error processing BasisCurve # for IfcTrimmedCurve #.
                return;
            }
            if (ifcBasisCurve.Curve == null)
            {
                // LOG: ERROR: Expected a single curve, not a curve loop for BasisCurve # for IfcTrimmedCurve #.
                return;
            }

            IFCData trim1 = ifcCurve.GetAttribute("Trim1");

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

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

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

            double param1 = 0.0, param2 = 0.0;

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

            Curve baseCurve = ifcBasisCurve.Curve;

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

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

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

                Curve = baseCurve.Clone();

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

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

                Curve copyCurve = baseCurve.Clone();

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

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

            CurveLoop = new CurveLoop();
            CurveLoop.Append(Curve);
        }
Esempio n. 20
0
        /// <summary>
        /// Processes an IfcRepresentationItem entity handle.
        /// </summary>
        /// <param name="ifcRepresentationItem">The IfcRepresentationItem handle.</param>
        /// <returns>The IFCRepresentationItem object.</returns>
        public static IFCRepresentationItem ProcessIFCRepresentationItem(IFCAnyHandle ifcRepresentationItem)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcRepresentationItem))
            {
                Importer.TheLog.LogNullError(IFCEntityType.IfcRepresentationItem);
                return(null);
            }

            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcBooleanResult))
            {
                return(IFCBooleanResult.ProcessIFCBooleanResult(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcCurve))
            {
                return(IFCCurve.ProcessIFCCurve(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcFaceBasedSurfaceModel))
            {
                return(IFCFaceBasedSurfaceModel.ProcessIFCFaceBasedSurfaceModel(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcGeometricSet))
            {
                return(IFCGeometricSet.ProcessIFCGeometricSet(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcMappedItem))
            {
                return(IFCMappedItem.ProcessIFCMappedItem(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcShellBasedSurfaceModel))
            {
                return(IFCShellBasedSurfaceModel.ProcessIFCShellBasedSurfaceModel(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcSolidModel))
            {
                return(IFCSolidModel.ProcessIFCSolidModel(ifcRepresentationItem));
            }

            if (IFCImportFile.TheFile.SchemaVersion >= IFCSchemaVersion.IFC2x2 && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcStyledItem))
            {
                return(IFCStyledItem.ProcessIFCStyledItem(ifcRepresentationItem));
            }

            if (IFCImportFile.TheFile.SchemaVersion >= IFCSchemaVersion.IFC4 && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcTriangulatedFaceSet))
            {
                return(IFCTriangulatedFaceSet.ProcessIFCTriangulatedFaceSet(ifcRepresentationItem));
            }

            // There is no way to actually determine an IFC4Add2 file vs. a "vanilla" IFC4 file, which is
            // obsolete.  The try/catch here allows us to read these obsolete files without crashing.
            try
            {
                if (IFCImportFile.TheFile.SchemaVersion >= IFCSchemaVersion.IFC4 && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcPolygonalFaceSet))
                {
                    return(IFCPolygonalFaceSet.ProcessIFCPolygonalFaceSet(ifcRepresentationItem));
                }
            }
            catch
            {
            }

            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcTopologicalRepresentationItem))
            {
                return(IFCTopologicalRepresentationItem.ProcessIFCTopologicalRepresentationItem(ifcRepresentationItem));
            }

            Importer.TheLog.LogUnhandledSubTypeError(ifcRepresentationItem, IFCEntityType.IfcRepresentationItem, true);
            return(null);
        }
      private double? GetTrimParameter(IFCData trim, IFCCurve basisCurve, IFCTrimmingPreference trimPreference, bool secondAttempt)
      {
         bool preferParam = !(trimPreference == IFCTrimmingPreference.Cartesian);
         if (secondAttempt)
            preferParam = !preferParam;
         double vertexEps = IFCImportFile.TheFile.Document.Application.VertexTolerance;

         IFCAggregate trimAggregate = trim.AsAggregate();
         foreach (IFCData trimParam in trimAggregate)
         {
            if (!preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Instance))
            {
               IFCAnyHandle trimParamInstance = trimParam.AsInstance();
               XYZ trimParamPt = IFCPoint.ProcessScaledLengthIFCCartesianPoint(trimParamInstance);
               if (trimParamPt == null)
               {
                  Importer.TheLog.LogWarning(basisCurve.Id, "Invalid trim point for basis curve.", false);
                  continue;
               }

               try
               {
                  IntersectionResult result = basisCurve.Curve.Project(trimParamPt);
                  if (result.Distance < vertexEps)
                     return result.Parameter;

                  Importer.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false);
               }
               catch
               {
                  Importer.TheLog.LogWarning(basisCurve.Id, "Cartesian value for trim point not on the basis curve.", false);
               }
            }
            else if (preferParam && (trimParam.PrimitiveType == IFCDataPrimitiveType.Double))
            {
               double trimParamDouble = trimParam.AsDouble();
               if (basisCurve.Curve.IsCyclic)
                  trimParamDouble = IFCUnitUtil.ScaleAngle(trimParamDouble);
               else
                  trimParamDouble = IFCUnitUtil.ScaleLength(trimParamDouble);
               return trimParamDouble;
            }
         }

         // Try again with opposite preference.
         if (!secondAttempt)
            return GetTrimParameter(trim, basisCurve, trimPreference, true);

         return null;
      }
Esempio n. 22
0
        /// <summary>
        /// Processes an IfcRepresentationItem entity handle.
        /// </summary>
        /// <param name="ifcRepresentationItem">The IfcRepresentationItem handle.</param>
        /// <returns>The IFCRepresentationItem object.</returns>
        public static IFCRepresentationItem ProcessIFCRepresentationItem(IFCAnyHandle ifcRepresentationItem)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcRepresentationItem))
            {
                Importer.TheLog.LogNullError(IFCEntityType.IfcRepresentationItem);
                return(null);
            }

            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcMappedItem))
            {
                return(IFCMappedItem.ProcessIFCMappedItem(ifcRepresentationItem));
            }
            if (IFCImportFile.TheFile.SchemaVersionAtLeast(IFCSchemaVersion.IFC2x2) && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcStyledItem))
            {
                return(IFCStyledItem.ProcessIFCStyledItem(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcTopologicalRepresentationItem))
            {
                return(IFCTopologicalRepresentationItem.ProcessIFCTopologicalRepresentationItem(ifcRepresentationItem));
            }

            // TODO: Move everything below to IFCGeometricRepresentationItem, once it is created.
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcBooleanResult))
            {
                return(IFCBooleanResult.ProcessIFCBooleanResult(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcCurve))
            {
                return(IFCCurve.ProcessIFCCurve(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcFaceBasedSurfaceModel))
            {
                return(IFCFaceBasedSurfaceModel.ProcessIFCFaceBasedSurfaceModel(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcGeometricSet))
            {
                return(IFCGeometricSet.ProcessIFCGeometricSet(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcPoint))
            {
                return(IFCPoint.ProcessIFCPoint(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcShellBasedSurfaceModel))
            {
                return(IFCShellBasedSurfaceModel.ProcessIFCShellBasedSurfaceModel(ifcRepresentationItem));
            }
            if (IFCAnyHandleUtil.IsValidSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcSolidModel))
            {
                return(IFCSolidModel.ProcessIFCSolidModel(ifcRepresentationItem));
            }

            // TODO: Move the items below to IFCGeometricRepresentationItem->IFCTessellatedItem->IfcTessellatedFaceSet.
            if (IFCImportFile.TheFile.SchemaVersionAtLeast(IFCSchemaVersion.IFC4Obsolete) && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcTriangulatedFaceSet))
            {
                return(IFCTriangulatedFaceSet.ProcessIFCTriangulatedFaceSet(ifcRepresentationItem));
            }
            // There is no way to actually determine an IFC4Add2 file vs. a "vanilla" IFC4 file, which is
            // obsolete.  The try/catch here allows us to read these obsolete files without crashing.
            try
            {
                if (IFCImportFile.TheFile.SchemaVersionAtLeast(IFCSchemaVersion.IFC4) && IFCAnyHandleUtil.IsSubTypeOf(ifcRepresentationItem, IFCEntityType.IfcPolygonalFaceSet))
                {
                    return(IFCPolygonalFaceSet.ProcessIFCPolygonalFaceSet(ifcRepresentationItem));
                }
            }
            catch (Exception ex)
            {
                // Once we fail once, downgrade the schema so we don't try again.
                if (IFCImportFile.HasUndefinedAttribute(ex))
                {
                    IFCImportFile.TheFile.DowngradeIFC4SchemaTo(IFCSchemaVersion.IFC4Add1Obsolete);
                }
                else
                {
                    throw ex;
                }
            }

            Importer.TheLog.LogUnhandledSubTypeError(ifcRepresentationItem, IFCEntityType.IfcRepresentationItem, true);
            return(null);
        }
      private void GetTrimParameters(IFCData trim1, IFCData trim2, IFCCurve basisCurve, IFCTrimmingPreference trimPreference,
          out double param1, out double param2)
      {
         double? condParam1 = GetTrimParameter(trim1, basisCurve, trimPreference, false);
         if (!condParam1.HasValue)
            throw new InvalidOperationException("#" + basisCurve.Id + ": Couldn't apply first trimming parameter of IfcTrimmedCurve.");
         param1 = condParam1.Value;

         double? condParam2 = GetTrimParameter(trim2, basisCurve, trimPreference, false);
         if (!condParam2.HasValue)
            throw new InvalidOperationException("#" + basisCurve.Id + ": Couldn't apply second trimming parameter of IfcTrimmedCurve.");
         param2 = condParam2.Value;

         if (MathUtil.IsAlmostEqual(param1, param2))
         {
            // If we had a cartesian parameter as the trim preference, check if the parameter values are better.
            if (trimPreference == IFCTrimmingPreference.Cartesian)
            {
               condParam1 = GetTrimParameter(trim1, basisCurve, IFCTrimmingPreference.Parameter, true);
               if (!condParam1.HasValue)
                  throw new InvalidOperationException("#" + basisCurve.Id + ": Couldn't apply first trimming parameter of IfcTrimmedCurve.");
               param1 = condParam1.Value;

               condParam2 = GetTrimParameter(trim2, basisCurve, IFCTrimmingPreference.Parameter, true);
               if (!condParam2.HasValue)
                  throw new InvalidOperationException("#" + basisCurve.Id + ": Couldn't apply second trimming parameter of IfcTrimmedCurve.");
               param2 = condParam2.Value;
            }
            else
               throw new InvalidOperationException("#" + basisCurve.Id + ": Ignoring 0 length curve.");
         }
      }
Esempio n. 24
0
        /// <summary>
        /// Processes IfcGridAxis attributes.
        /// </summary>
        /// <param name="ifcGridAxis">The IfcGridAxis handle.</param>
        protected override void Process(IFCAnyHandle ifcGridAxis)
        {
            base.Process(ifcGridAxis);

            AxisTag = IFCImportHandleUtil.GetOptionalStringAttribute(ifcGridAxis, "AxisTag", null);
            if (AxisTag == null)
            {
                AxisTag = "Z"; // arbitrary; all Revit Grids have names.
            }
            IFCAnyHandle axisCurve = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcGridAxis, "AxisCurve", true);

            AxisCurve = IFCCurve.ProcessIFCCurve(axisCurve);

            bool found     = false;
            bool sameSense = IFCImportHandleUtil.GetRequiredBooleanAttribute(ifcGridAxis, "SameSense", out found);

            SameSense = found ? sameSense : true;

            // We are going to check if this grid axis is a vertical duplicate of any existing axis.
            // If so, we will throw an exception so that we don't create duplicate grids.
            // We will only initialize these values if we actually intend to use them below.
            IList <Curve> curves     = null;
            int           curveCount = 0;

            ElementId gridId = ElementId.InvalidElementId;

            if (Importer.TheCache.GridNameToElementMap.TryGetValue(AxisTag, out gridId))
            {
                Grid grid = IFCImportFile.TheFile.Document.GetElement(gridId) as Grid;
                if (grid != null)
                {
                    IList <Curve> otherCurves = new List <Curve>();
                    Curve         gridCurve   = grid.Curve;
                    if (gridCurve != null)
                    {
                        otherCurves.Add(gridCurve);
                        int matchingGridId = FindMatchingGrid(otherCurves, grid.Id.IntegerValue, ref curves, ref curveCount);

                        if (matchingGridId != -1)
                        {
                            Importer.TheCache.UseGrid(grid);
                            CreatedElementId = grid.Id;
                            return;
                        }
                    }
                }
            }

            IDictionary <string, IFCGridAxis> gridAxes = IFCImportFile.TheFile.IFCProject.GridAxes;
            IFCGridAxis gridAxis = null;

            if (gridAxes.TryGetValue(AxisTag, out gridAxis))
            {
                int matchingGridId = FindMatchingGrid(gridAxis, ref curves, ref curveCount);
                if (matchingGridId != -1)
                {
                    DuplicateAxisId = matchingGridId;
                    return;
                }
                else
                {
                    // Revit doesn't allow grid lines to have the same name.  If it isn't a duplicate, rename it.
                    // Note that this will mean that we may miss some "duplicate" grid lines because of the renaming.
                    AxisTag = MakeAxisTagUnique(AxisTag);
                }
            }

            gridAxes.Add(new KeyValuePair <string, IFCGridAxis>(AxisTag, this));
        }
Esempio n. 25
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

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

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

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

            double shortCurveTol = IFCImportFile.TheFile.Document.Application.ShortCurveTolerance;

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

            Segments.Clear();

            ShortGapRepairer shortGapRepairer = new ShortGapRepairer(shortCurveTol);

            foreach (IFCAnyHandle segment in segments)
            {
                IFCCurve currCurve = ProcessIFCCompositeCurveSegment(segment);

                if (currCurve != null)
                {
                    Segments.Add(currCurve);
                    IList <Curve> newCurves = currCurve.GetCurves();
                    if (newCurves != null && newCurves.Count != 0)
                    {
                        curveSegments.AddRange(newCurves);
                        // If we had a gap, we weren't able to correct it before getting new curves.
                        shortGapRepairer.ClearGapInformation();
                    }
                    else
                    {
                        Line gapRepairLine = shortGapRepairer.AddToGap(currCurve.Id,
                                                                       currCurve.BackupCurveStartLocation, currCurve.BackupCurveEndLocation);
                        if (gapRepairLine != null)
                        {
                            curveSegments.Add(gapRepairLine);
                        }
                    }
                }
            }

            int numSegments = curveSegments.Count;

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

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

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

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

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

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

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

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

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

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

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

                        minGap = Math.Min(minStartGap, minEndGap);

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

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

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

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

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

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

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

                        continue;
                    }

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

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

                    if (attachNextSegmentToEnd)
                    {
                        // Update the curve loop end point to be the end point of the next segment after potentially being reversed.
                        XYZ originalCurveLoopEndPoint = curveLoopEndPoint;
                        curveLoopEndPoint = nextEndPoint;
                        if (canRepairNext)
                        {
                            curveSegments[ii] = RepairLineAndReport(Id, originalCurveLoopEndPoint, curveLoopEndPoint, minGap);
                        }
                        else if (curveSegments[ii - 1] is Line) // = canRepairCurrent, only used here.
                        {
                            curveSegments[ii - 1] = RepairLineAndReport(Id, curveSegments[ii - 1].GetEndPoint(0), curveSegments[ii].GetEndPoint(0), minGap);
                        }
                        else
                        {
                            // Can't add a line to fix a gap that is smaller than the short curve tolerance.
                            // This will result in mutliple curve loops.
                            if (minGap < shortCurveTol + MathUtil.Eps())
                            {
                                Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that is too short to be repaired by a connecting segment.", false);
                            }
                            else
                            {
                                try
                                {
                                    Line repairLine = Line.CreateBound(originalCurveLoopEndPoint, curveSegments[ii].GetEndPoint(0));
                                    curveSegments.Insert(ii, repairLine);
                                    ii++; // Skip the repair line as we've already "added" it and the non-linear segment to our growing loop.
                                    numSegments++;
                                    createdRepairLine = true;
                                }
                                catch
                                {
                                    Importer.TheLog.LogError(Id, "IfcCompositeCurve contains a gap between two non-linear segments that can't be fixed.", false);
                                }
                            }
                        }
                    }
                    else
                    {
                        XYZ originalCurveLoopStartPoint = curveLoopStartPoint;
                        curveLoopStartPoint = nextStartPoint;

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

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

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

                        canRepairFirst = true;

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

                SetCurveLoops(curveSegments);
            }
            catch (Exception ex)
            {
                Importer.TheLog.LogError(Id, ex.Message, true);
            }
        }
Esempio n. 26
0
        /// <summary>
        /// Create an IFCCurve object from a handle of type IfcCurve.
        /// </summary>
        /// <param name="ifcCurve">The IFC handle.</param>
        /// <returns>The IFCCurve object.</returns>
        public static IFCCurve ProcessIFCCurve(IFCAnyHandle ifcCurve)
        {
            if (IFCAnyHandleUtil.IsNullOrHasNoValue(ifcCurve))
            {
                IFCImportFile.TheLog.LogNullError(IFCEntityType.IfcCurve); 
                return null;
            }

            IFCEntity curve;
            if (!IFCImportFile.TheFile.EntityMap.TryGetValue(ifcCurve.StepId, out curve))
                curve = new IFCCurve(ifcCurve);
            return (curve as IFCCurve); 
        }
Esempio n. 27
0
        private void ProcessIFCTrimmedCurve(IFCAnyHandle ifcCurve)
        {
            bool found = false;

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

            if (!found)
            {
                sameSense = true;
            }

            IFCAnyHandle basisCurve    = IFCImportHandleUtil.GetRequiredInstanceAttribute(ifcCurve, "BasisCurve", true);
            IFCCurve     ifcBasisCurve = IFCCurve.ProcessIFCCurve(basisCurve);

            if (ifcBasisCurve == null || (ifcBasisCurve.Curve == null && ifcBasisCurve.CurveLoop == null))
            {
                // LOG: ERROR: Error processing BasisCurve # for IfcTrimmedCurve #.
                return;
            }
            if (ifcBasisCurve.Curve == null)
            {
                // LOG: ERROR: Expected a single curve, not a curve loop for BasisCurve # for IfcTrimmedCurve #.
                return;
            }

            IFCData trim1 = ifcCurve.GetAttribute("Trim1");

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

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

            string trimPreferenceAsString        = IFCAnyHandleUtil.GetEnumerationAttribute(ifcCurve, "MasterRepresentation");
            IFCTrimmingPreference trimPreference = IFCTrimmingPreference.Parameter;

            if (trimPreferenceAsString != null)
            {
                trimPreference = (IFCTrimmingPreference)Enum.Parse(typeof(IFCTrimmingPreference), trimPreferenceAsString, true);
            }

            double param1 = 0.0, param2 = 0.0;

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

            Curve baseCurve = ifcBasisCurve.Curve;

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

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

                if (param2 - param1 > 2.0 * Math.PI - MathUtil.Eps())
                {
                    // LOG: WARNING: #Id: IfcTrimmedCurve length is greater than 2*PI, leaving unbound.
                    Curve = baseCurve;
                    return;
                }

                Curve = baseCurve.Clone();
                Curve.MakeBound(param1, param2);
            }
            else
            {
                if (MathUtil.IsAlmostEqual(param1, param2))
                {
                    // LOG: ERROR: Param1 = Param2 for IfcTrimmedCurve #, ignoring.
                    return;
                }

                if (param1 > param2 - MathUtil.Eps())
                {
                    // LOG: WARNING: Param1 > Param2 for IfcTrimmedCurve #, reversing.
                    MathUtil.Swap(ref param1, ref param2);
                    return;
                }

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