예제 #1
0
        /// <summary>
        /// Gets aggregate attribute values from a handle.
        /// </summary>
        /// <typeparam name="T">The return type.</typeparam>
        /// <param name="handle">The handle.</param>
        /// <param name="name">The attribute name.</param>
        /// <returns>The collection of attribute values.</returns>
        public static T GetAggregateInstanceAttribute <T>(IFCAnyHandle handle, string name) where T : ICollection <IFCAnyHandle>, new()
        {
            if (handle == null)
            {
                throw new ArgumentNullException("handle");
            }

            if (!handle.HasValue)
            {
                throw new ArgumentException("Invalid handle.");
            }

            IFCData ifcData = handle.GetAttribute(name);

            T aggregateAttribute = default(T);

            if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
            {
                IFCAggregate aggregate = ifcData.AsAggregate();
                if (aggregate != null)
                {
                    aggregateAttribute = new T();
                    foreach (IFCData val in aggregate)
                    {
                        if (val.PrimitiveType == IFCDataPrimitiveType.Instance)
                        {
                            aggregateAttribute.Add(val.AsInstance());
                        }
                    }
                }
            }
            return(aggregateAttribute);
        }
예제 #2
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);
        }
예제 #3
0
        private double?GetRawTrimParameter(IFCData trim)
        {
            IFCAggregate trimAggregate = trim.AsAggregate();

            foreach (IFCData trimParam in trimAggregate)
            {
                if (trimParam.PrimitiveType == IFCDataPrimitiveType.Double)
                {
                    return(trimParam.AsDouble());
                }
            }

            return(null);
        }
        /// <summary>
        /// Get attribute of type IList of IList of Entity
        /// </summary>
        /// <param name="handle">The handle</param>
        /// <param name="name">attribute name</param>
        /// <returns>IList of IList of Entity</returns>
        public static IList <IList <IFCAnyHandle> > GetListOfListOfInstanceAttribute(IFCAnyHandle handle, string name)
        {
            if (handle == null)
            {
                throw new ArgumentNullException("handle");
            }

            if (!handle.HasValue)
            {
                throw new ArgumentException("Invalid handle.");
            }

            IList <IList <IFCAnyHandle> > outerList = null;

            IFCData ifcData = handle.GetAttribute(name);

            if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
            {
                IFCAggregate outer = ifcData.AsAggregate();
                if (outer != null)
                {
                    outerList = new List <IList <IFCAnyHandle> >();

                    foreach (IFCData outerVal in outer)
                    {
                        IFCAggregate inner = outerVal.AsAggregate();

                        if (inner != null)
                        {
                            IList <IFCAnyHandle> innerList = new List <IFCAnyHandle>();
                            foreach (IFCData innerVal in inner)
                            {
                                innerList.Add(innerVal.AsInstance());
                            }
                            outerList.Add(innerList);
                        }
                    }
                }
            }
            return(outerList);
        }
예제 #5
0
        /// <summary>
        /// Checks if an object handle has IfcRelDecomposes.
        /// </summary>
        /// <param name="objectHandle">The object handle.</param>
        /// <returns>True if it has, false if not.</returns>
        public static bool HasRelDecomposes(IFCAnyHandle objectHandle)
        {
            if (objectHandle == null)
            {
                throw new ArgumentNullException("objectHandle");
            }

            if (!objectHandle.HasValue)
            {
                throw new ArgumentException("Invalid handle.");
            }

            if (!IsSubTypeOf(objectHandle, IFCEntityType.IfcObject) &&
                !IsSubTypeOf(objectHandle, IFCEntityType.IfcTypeObject))
            {
                throw new ArgumentException("The operation is not valid for this handle.");
            }

            IFCData ifcData = objectHandle.GetAttribute("Decomposes");

            if (!ifcData.HasValue)
            {
                return(false);
            }
            else if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
            {
                IFCAggregate aggregate = ifcData.AsAggregate();
                if (aggregate != null && aggregate.Count > 0)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            throw new InvalidOperationException("Failed to get decomposes.");
        }
예제 #6
0
        /// <summary>
        /// Gets the coordinates of an IfcCartesianPoint.
        /// </summary>
        /// <param name="axisPlacement">The IfcCartesianPoint.</param>
        /// <returns>The list of coordinates.</returns>
        public static IList <double> GetCoordinates(IFCAnyHandle cartesianPoint)
        {
            IList <double> coordinates = null;

            if (cartesianPoint == null)
            {
                throw new ArgumentNullException("cartesianPoint");
            }

            if (!cartesianPoint.HasValue)
            {
                throw new ArgumentException("Invalid handle.");
            }

            if (!IsSubTypeOf(cartesianPoint, IFCEntityType.IfcCartesianPoint))
            {
                throw new ArgumentException("Not an IfcCartesianPoint handle.");
            }

            IFCData ifcData = cartesianPoint.GetAttribute("Coordinates");

            if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
            {
                IFCAggregate aggregate = ifcData.AsAggregate();
                if (aggregate != null && aggregate.Count > 0)
                {
                    coordinates = new List <double>();
                    foreach (IFCData val in aggregate)
                    {
                        if (val.PrimitiveType == IFCDataPrimitiveType.Double)
                        {
                            coordinates.Add(val.AsDouble());
                        }
                    }
                }
            }

            return(coordinates);
        }
예제 #7
0
        /// <summary>
        /// Gets IfcRelDecomposes of an object handle.
        /// </summary>
        /// <param name="objectHandle">The object handle.</param>
        /// <returns>The collection of IfcRelDecomposes.</returns>
        public static HashSet <IFCAnyHandle> GetRelDecomposes(IFCAnyHandle objectHandle)
        {
            if (objectHandle == null)
            {
                throw new ArgumentNullException("objectHandle");
            }

            if (!objectHandle.HasValue)
            {
                throw new ArgumentException("Invalid handle.");
            }

            if (!IsSubTypeOf(objectHandle, IFCEntityType.IfcObject) &&
                !IsSubTypeOf(objectHandle, IFCEntityType.IfcTypeObject))
            {
                throw new ArgumentException("The operation is not valid for this handle.");
            }

            HashSet <IFCAnyHandle> decomposes = new HashSet <IFCAnyHandle>();
            IFCData ifcData = objectHandle.GetAttribute("IsDecomposedBy");

            if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
            {
                IFCAggregate aggregate = ifcData.AsAggregate();
                if (aggregate != null && aggregate.Count > 0)
                {
                    foreach (IFCData val in aggregate)
                    {
                        if (val.PrimitiveType == IFCDataPrimitiveType.Instance)
                        {
                            decomposes.Add(val.AsInstance());
                        }
                    }
                }
            }
            return(decomposes);
        }
예제 #8
0
        /// <summary>
        /// Gets IfcMaterialDefinitionRepresentation inverse set of an IfcMaterial handle.
        /// </summary>
        /// <param name="objectHandle">The IfcMaterial handle.</param>
        /// <returns>The collection of IfcMaterialDefinitionRepresentation.</returns>
        public static HashSet <IFCAnyHandle> GetHasRepresentation(IFCAnyHandle objectHandle)
        {
            if (objectHandle == null)
            {
                throw new ArgumentNullException("objectHandle");
            }

            if (!objectHandle.HasValue)
            {
                throw new ArgumentException("Invalid handle.");
            }

            if (!IsSubTypeOf(objectHandle, IFCEntityType.IfcMaterial))
            {
                throw new ArgumentException("The operation is not valid for this handle.");
            }

            HashSet <IFCAnyHandle> hasRepresentation = new HashSet <IFCAnyHandle>();
            IFCData ifcData = objectHandle.GetAttribute("HasRepresentation");

            if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
            {
                IFCAggregate aggregate = ifcData.AsAggregate();
                if (aggregate != null && aggregate.Count > 0)
                {
                    foreach (IFCData val in aggregate)
                    {
                        if (val.PrimitiveType == IFCDataPrimitiveType.Instance)
                        {
                            hasRepresentation.Add(val.AsInstance());
                        }
                    }
                }
            }
            return(hasRepresentation);
        }
예제 #9
0
        /// <summary>
        /// Sets IFCValue aggregate attribute for the handle.
        /// </summary>
        /// <remarks>
        /// If values collection is null, the attribute will be unset.
        /// </remarks>
        /// <param name="handle">The handle.</param>
        /// <param name="name">The attribute name.</param>
        /// <param name="values">The values.</param>
        /// <exception cref="ArgumentException">If the name is null or empty.</exception>
        public static void SetAttribute(IFCAnyHandle handle, string name, ICollection <IFCData> values)
        {
            if (String.IsNullOrEmpty(name))
            {
                throw new ArgumentException("The name is empty.", "name");
            }

            if (values != null)
            {
                if (values.Contains(null))
                {
                    throw new ArgumentException("The collection contains null values.", "values");
                }

                IFCAggregate aggregateAttribute = handle.CreateAggregateAttribute(name);
                if (aggregateAttribute != null)
                {
                    foreach (IFCData value in values)
                    {
                        aggregateAttribute.Add(value);
                    }
                }
            }
        }
예제 #10
0
        /// <summary>
        /// Gets representations of a representation handle.
        /// </summary>
        /// <param name="representation">The representation handle.</param>
        /// <returns>The list of representations.</returns>
        public static List <IFCAnyHandle> GetRepresentations(IFCAnyHandle representation)
        {
            if (representation == null)
            {
                throw new ArgumentNullException("representation");
            }

            if (!representation.HasValue)
            {
                throw new ArgumentException("Invalid handle.");
            }

            if (!IsSubTypeOf(representation, IFCEntityType.IfcProductRepresentation))
            {
                throw new ArgumentException("The operation is not valid for this handle.");
            }

            List <IFCAnyHandle> representations = new List <IFCAnyHandle>();
            IFCData             ifcData         = representation.GetAttribute("Representations");

            if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
            {
                IFCAggregate aggregate = ifcData.AsAggregate();
                if (aggregate != null && aggregate.Count > 0)
                {
                    foreach (IFCData val in aggregate)
                    {
                        if (val.PrimitiveType == IFCDataPrimitiveType.Instance)
                        {
                            representations.Add(val.AsInstance());
                        }
                    }
                }
            }
            return(representations);
        }
예제 #11
0
        /// <summary>
        /// Exports materials for host object.
        /// </summary>
        /// <param name="exporterIFC">
        /// The ExporterIFC object.
        /// </param>
        /// <param name="hostObject">
        /// The host object.
        /// </param>
        /// <param name="elemHnds">
        /// The host IFC handles.
        /// </param>
        /// <param name="geometryElement">
        /// The geometry element.
        /// </param>
        /// <param name="productWrapper">
        /// The IFCProductWrapper.
        /// </param>
        /// <param name="levelId">
        /// The level id.
        /// </param>
        /// <param name="direction">
        /// The IFCLayerSetDirection.
        /// </param>
        /// <returns>
        /// True if exported successfully, false otherwise.
        /// </returns>
        public static bool ExportHostObjectMaterials(ExporterIFC exporterIFC, HostObject hostObject,
                                                     IList <IFCAnyHandle> elemHnds, GeometryElement geometryElement, IFCProductWrapper productWrapper,
                                                     ElementId levelId, Toolkit.IFCLayerSetDirection direction)
        {
            if (hostObject == null)
            {
                return(true); //nothing to do
            }
            if (elemHnds == null || (elemHnds.Count == 0))
            {
                return(true); //nothing to do
            }
            IFCFile file = exporterIFC.GetFile();

            // Roofs with no components are only allowed one material.  We will arbitrarily choose the thickest material.
            IFCAnyHandle primaryMaterialHnd = null;

            using (IFCTransaction tr = new IFCTransaction(file))
            {
                if (productWrapper != null)
                {
                    productWrapper.ClearFinishMaterials();
                }

                double scale = exporterIFC.LinearScale;

                double scaledOffset = 0.0, scaledWallWidth = 0.0, wallHeight = 0.0;
                Wall   wall = hostObject as Wall;
                if (wall != null)
                {
                    scaledWallWidth = wall.Width * scale;
                    scaledOffset    = -scaledWallWidth / 2.0;
                    BoundingBoxXYZ boundingBox = wall.get_BoundingBox(null);
                    if (boundingBox != null)
                    {
                        wallHeight = boundingBox.Max.Z - boundingBox.Min.Z;
                    }
                }

                ElementId    typeElemId       = hostObject.GetTypeId();
                IFCAnyHandle materialLayerSet = ExporterCacheManager.MaterialLayerSetCache.Find(typeElemId);
                if (IFCAnyHandleUtil.IsNullOrHasNoValue(materialLayerSet))
                {
                    HostObjAttributes hostObjAttr = hostObject.Document.GetElement(typeElemId) as HostObjAttributes;
                    if (hostObjAttr == null)
                    {
                        return(true); //nothing to do
                    }
                    List <ElementId> matIds = new List <ElementId>();
                    List <double>    widths = new List <double>();
                    List <MaterialFunctionAssignment> functions = new List <MaterialFunctionAssignment>();
                    ElementId         baseMatId = CategoryUtil.GetBaseMaterialIdForElement(hostObject);
                    CompoundStructure cs        = hostObjAttr.GetCompoundStructure();
                    if (cs != null)
                    {
                        //TODO: Vertically compound structures are not yet supported by export.
                        if (!cs.IsVerticallyHomogeneous() && !MathUtil.IsAlmostZero(wallHeight))
                        {
                            cs = cs.GetSimpleCompoundStructure(wallHeight, wallHeight / 2.0);
                        }

                        for (int i = 0; i < cs.LayerCount; ++i)
                        {
                            ElementId matId = cs.GetMaterialId(i);
                            if (matId != ElementId.InvalidElementId)
                            {
                                matIds.Add(matId);
                            }
                            else
                            {
                                matIds.Add(baseMatId);
                            }
                            widths.Add(cs.GetLayerWidth(i));
                            // save layer function into IFCProductWrapper,
                            // it's used while exporting "Function" of Pset_CoveringCommon
                            functions.Add(cs.GetLayerFunction(i));
                        }
                    }

                    if (matIds.Count == 0)
                    {
                        matIds.Add(baseMatId);
                        widths.Add(cs != null ? cs.GetWidth() : 0);
                        functions.Add(MaterialFunctionAssignment.None);
                    }

                    List <IFCAnyHandle> layers = new List <IFCAnyHandle>();
                    double thickestLayer       = 0.0;
                    for (int i = 0; i < matIds.Count; ++i)
                    {
                        if (widths[i] < MathUtil.Eps())
                        {
                            continue;
                        }

                        IFCAnyHandle materialHnd = CategoryUtil.GetOrCreateMaterialHandle(hostObjAttr.Document, exporterIFC, matIds[i]);
                        if (primaryMaterialHnd == null || (widths[i] > thickestLayer))
                        {
                            primaryMaterialHnd = materialHnd;
                            thickestLayer      = widths[i];
                        }

                        double       scaledWidth   = widths[i] * scale;
                        IFCAnyHandle materialLayer = IFCInstanceExporter.CreateMaterialLayer(file, materialHnd, scaledWidth, null);
                        layers.Add(materialLayer);
                        if ((productWrapper != null) && (functions[i] == MaterialFunctionAssignment.Finish1 || functions[i] == MaterialFunctionAssignment.Finish2))
                        {
                            productWrapper.AddFinishMaterial(materialHnd);
                        }
                    }

                    if (layers.Count == 0)
                    {
                        return(false);
                    }

                    string layerSetName = NamingUtil.CreateIFCFamilyName(exporterIFC, -1);
                    materialLayerSet = IFCInstanceExporter.CreateMaterialLayerSet(file, layers, layerSetName);

                    ExporterCacheManager.MaterialLayerSetCache.Register(typeElemId, materialLayerSet);
                }

                // IfcMaterialLayerSetUsage is not supported for IfcWall, only IfcWallStandardCase.
                IFCAnyHandle layerSetUsage = null;
                for (int ii = 0; ii < elemHnds.Count; ii++)
                {
                    IFCAnyHandle elemHnd = elemHnds[ii];
                    if (IFCAnyHandleUtil.IsNullOrHasNoValue(elemHnd))
                    {
                        continue;
                    }

                    HashSet <IFCAnyHandle> relDecomposesSet = IFCAnyHandleUtil.GetRelDecomposes(elemHnd);

                    IList <IFCAnyHandle> subElemHnds = new List <IFCAnyHandle>();
                    if (relDecomposesSet != null && relDecomposesSet.Count == 1)
                    {
                        IFCAnyHandle relAggregates = relDecomposesSet.First();
                        if (IFCAnyHandleUtil.IsTypeOf(relAggregates, IFCEntityType.IfcRelAggregates))
                        {
                            IFCData ifcData = relAggregates.GetAttribute("RelatedObjects");
                            if (ifcData.PrimitiveType == IFCDataPrimitiveType.Aggregate)
                            {
                                IFCAggregate aggregate = ifcData.AsAggregate();
                                if (aggregate != null && aggregate.Count > 0)
                                {
                                    foreach (IFCData val in aggregate)
                                    {
                                        if (val.PrimitiveType == IFCDataPrimitiveType.Instance)
                                        {
                                            subElemHnds.Add(val.AsInstance());
                                        }
                                    }
                                }
                            }
                        }
                    }

                    bool hasSubElems = !(subElemHnds.Count == 0);
                    bool isRoof      = IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcRoof);
                    if (!hasSubElems && !isRoof && !IFCAnyHandleUtil.IsTypeOf(elemHnd, IFCEntityType.IfcWall))
                    {
                        if (layerSetUsage == null)
                        {
                            bool flipDirSense = true;
                            if (wall != null)
                            {
                                // if we have flipped the center curve on export, we need to take that into account here.
                                // We flip the center curve on export if it is an arc and it has a negative Z direction.
                                LocationCurve locCurve = wall.Location as LocationCurve;
                                if (locCurve != null)
                                {
                                    Curve curve        = locCurve.Curve;
                                    Plane defPlane     = new Plane(XYZ.BasisX, XYZ.BasisY, XYZ.Zero);
                                    bool  curveFlipped = GeometryUtil.MustFlipCurve(defPlane, curve);
                                    flipDirSense = !(wall.Flipped ^ curveFlipped);
                                }
                            }
                            else if (hostObject is Floor)
                            {
                                flipDirSense = false;
                            }

                            double            offsetFromReferenceLine = flipDirSense ? -scaledOffset : scaledOffset;
                            IFCDirectionSense sense = flipDirSense ? IFCDirectionSense.Negative : IFCDirectionSense.Positive;

                            layerSetUsage = IFCInstanceExporter.CreateMaterialLayerSetUsage(file, materialLayerSet, direction, sense, offsetFromReferenceLine);
                        }
                        ExporterCacheManager.MaterialLayerRelationsCache.Add(layerSetUsage, elemHnd);
                    }
                    else
                    {
                        if (hasSubElems)
                        {
                            foreach (IFCAnyHandle subElemHnd in subElemHnds)
                            {
                                if (!IFCAnyHandleUtil.IsNullOrHasNoValue(subElemHnd))
                                {
                                    ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, subElemHnd);
                                }
                            }
                        }
                        else if (!isRoof)
                        {
                            ExporterCacheManager.MaterialLayerRelationsCache.Add(materialLayerSet, elemHnd);
                        }
                        else if (primaryMaterialHnd != null)
                        {
                            ExporterCacheManager.MaterialLayerRelationsCache.Add(primaryMaterialHnd, elemHnd);
                        }
                    }

                    exporterIFC.RegisterSpaceBoundingElementHandle(elemHnd, hostObject.Id, levelId);
                }

                tr.Commit();
                return(true);
            }
        }
예제 #12
0
        protected override void Process(IFCAnyHandle ifcCurve)
        {
            base.Process(ifcCurve);

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

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

            IList <IFCData> segments = null;

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

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

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

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

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

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

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

                    IFCAggregate segmentInfo = segment.AsAggregate();

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

                            int validCurrentIndex = currentIndex.Value;
                            if (lastIndex != validCurrentIndex)
                            {
                                pointXYZs.Add(pointListXYZs[validCurrentIndex]);
                                currentLineSegmentPoints.Add(pointListXYZs[validCurrentIndex]);
                                lastIndex = validCurrentIndex;
                            }
                        }
                    }
                    else if (indexType.Equals("IfcArcIndex", StringComparison.OrdinalIgnoreCase))
                    {
                        // Create any line segments that haven't been already created.
                        CreateLineSegments(curveLoop, currentLineSegmentPoints);

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

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

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

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

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

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

            SetCurveLoop(curveLoop, pointXYZs);
        }