Beispiel #1
0
        public static IList <CurveLoop> TrimCurveLoops(int id, IFCCurve ifcCurve, double startVal, double?origEndVal)
        {
            if (ifcCurve.CurveLoops == null)
            {
                return(null);
            }

            if (!NeedsTrimming(startVal, origEndVal))
            {
                return(ifcCurve.CurveLoops);
            }

            if (ifcCurve.CurveLoops.Count != 1)
            {
                Importer.TheLog.LogError(id, "Ignoring potential trimming for disjoint curve.", false);
                return(ifcCurve.CurveLoops);
            }

            CurveLoop trimmedDirectrix = TrimCurveLoop(id, ifcCurve, startVal, origEndVal);

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

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

            trimmedDirectrices.Add(trimmedDirectrix);
            return(trimmedDirectrices);
        }
Beispiel #2
0
        /// <summary>
        /// Specifically check if the trim parameters are likely set incorrectly to the sum of the lengths of the curve segments,
        /// if some of the curve segments are line segments.
        /// </summary>
        /// <param name="id">The id of the IFC entity containing the directrix, for messaging purposes.</param>
        /// <param name="ifcCurve">The IFCCurve entity containing the CurveLoop to be trimmed.</param>
        /// <param name="startVal">The starting trim parameter.</param>
        /// <param name="endVal">The ending trim parameter.</param>
        /// <param name="totalParamLength">The total parametric length of the curve, as defined by IFC.</param>
        /// <returns>False if the trim parameters are thought to be invalid or unnecessary, true otherwise.</returns>
        private static bool CheckIfTrimParametersAreNeeded(int id, IFCCurve ifcCurve,
                                                           double startVal, double endVal, double totalParamLength)
        {
            // This check allows for some leniency in the setting of startVal and endVal; we assume that:
            // 1. If the parameter range is equal, that an offset value is OK; don't trim.
            // 2. If the start parameter is 0 and the curveParamLength is greater than the total length, don't trim.
            double curveParamLength = endVal - startVal;

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

            if (MathUtil.IsAlmostZero(startVal) && totalParamLength < curveParamLength - MathUtil.Eps())
            {
                return(false);
            }

            if (!(ifcCurve is IFCCompositeCurve))
            {
                return(true);
            }

            double totalRawParametricLength = 0.0;

            foreach (IFCCurve curveSegment in (ifcCurve as IFCCompositeCurve).Segments)
            {
                if (!(curveSegment is IFCTrimmedCurve))
                {
                    return(true);
                }

                IFCTrimmedCurve trimmedCurveSegment = curveSegment as IFCTrimmedCurve;
                if (trimmedCurveSegment.Trim1 == null || trimmedCurveSegment.Trim2 == null)
                {
                    return(true);
                }

                totalRawParametricLength += (trimmedCurveSegment.Trim2.Value - trimmedCurveSegment.Trim1.Value);
            }

            // Error in some Tekla files - lines are parameterized by length, instead of 1.0 (as is correct).
            // Warn and ignore the parameter length.  This must come after the MathUtil.IsAlmostEqual(curveParamLength, totalParamLength)
            // check above, since we don't want to warn if curveParamLength == totalParamLength.
            if (MathUtil.IsAlmostEqual(curveParamLength, totalRawParametricLength))
            {
                Importer.TheLog.LogWarning(id, "The total parameter length for this curve is equal to the sum of the parameter deltas, " +
                                           "and not the parameter length as defined in IFC.  " +
                                           "Most likely, this is an error in the sending application, and the trim extents are being ignored.  " +
                                           "If this trim was intended, please contact Autodesk.", true);
                return(false);
            }

            return(true);
        }
Beispiel #3
0
        /// <summary>
        /// Specifically check if the trim parameters are likely set incorrectly to the sum of the lengths of the curve segments,
        /// if some of the curve segments are line segments.
        /// </summary>
        /// <param name="id">The id of the IFC entity containing the directrix, for messaging purposes.</param>
        /// <param name="ifcCurve">The IFCCurve entity containing the CurveLoop to be trimmed.</param>
        /// <param name="curveParamLength">The delta between the start and end parameters of the overall curve.</param>
        /// <returns>False if the trim parameters are thought to be invalid, true otherwise.</returns>
        private static bool CheckIfTrimParametersAreValidForSomeInvalidities(int id, IFCCurve ifcCurve, double curveParamLength)
        {
            if (!(ifcCurve is IFCCompositeCurve))
            {
                return(true);
            }

            double totalRawParametricLength = 0.0;

            foreach (IFCCurve curveSegment in (ifcCurve as IFCCompositeCurve).Segments)
            {
                if (!(curveSegment is IFCTrimmedCurve))
                {
                    return(true);
                }

                IFCTrimmedCurve trimmedCurveSegment = curveSegment as IFCTrimmedCurve;
                if (trimmedCurveSegment.Trim1 == null || trimmedCurveSegment.Trim2 == null)
                {
                    return(true);
                }

                totalRawParametricLength += (trimmedCurveSegment.Trim2.Value - trimmedCurveSegment.Trim1.Value);
            }

            if (MathUtil.IsAlmostEqual(curveParamLength, totalRawParametricLength))
            {
                Importer.TheLog.LogWarning(id, "The total parameter length for this curve is equal to the sum of the parameter deltas, " +
                                           "and not the parameter length as defined in IFC.  " +
                                           "Most likely, this is an error in the sending application, and the trim extents are being ignored.  " +
                                           "If this trim was intended, please contact Autodesk.", true);
                return(false);
            }

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

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

            // Trivial case: unbound curve.
            Curve possiblyUnboundCurve = origCurveLoop.First();

            if (!possiblyUnboundCurve.IsBound)
            {
                if (!origEndVal.HasValue)
                {
                    Importer.TheLog.LogError(id, "Can't trim unbound curve with no given end parameter.", true);
                }

                CurveLoop boundCurveLoop = new CurveLoop();
                Curve     boundCurve     = possiblyUnboundCurve.Clone();
                boundCurve.MakeBound(startVal, origEndVal.Value * ifcCurve.ParametericScaling);
                boundCurveLoop.Append(boundCurve);
                return(boundCurveLoop);
            }

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

            double totalParamLength = 0.0;

            bool allLines = true;

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

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

            double endVal = origEndVal.HasValue ? origEndVal.Value : totalParamLength;
            double eps    = MathUtil.Eps();

            if (!CheckIfTrimParametersAreNeeded(id, ifcCurve, startVal, endVal, totalParamLength))
            {
                return(origCurveLoop);
            }

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

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

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

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

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

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

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

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

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

            CurveLoop trimmedCurveLoop = new CurveLoop();

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

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

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

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

            double totalParamLength = 0.0;

            bool allLines = true;

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

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

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

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

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

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

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

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

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

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

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

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

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

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

                    newLoopCurves.Add(newCurve);
                    break;
                }
            }

            CurveLoop trimmedCurveLoop = new CurveLoop();

            foreach (Curve curve in newLoopCurves)
            {
                trimmedCurveLoop.Append(curve);
            }
            return(trimmedCurveLoop);
        }