Ejemplo n.º 1
0
        private string CalculateDoorOperationStyle(FamilyInstance currElem, Transform trf)
        {
            int    leftPosYArcCount     = 0;
            int    leftNegYArcCount     = 0;
            int    rightPosYArcCount    = 0;
            int    rightNegYArcCount    = 0;
            int    fullCircleCount      = 0;
            int    leftHalfCircleCount  = 0;
            int    rightHalfCircleCount = 0;
            double allowance            = 0.0001;

            if (currElem == null)
            {
                return("NOTDEFINED");
            }

            FamilySymbol famSymbol = currElem.Symbol;

            if (famSymbol == null)
            {
                return("NOTDEFINED");
            }
            Family fam = famSymbol.Family;

            if (fam == null)
            {
                return("NOTDEFINED");
            }

            Transform doorWindowTrf = ExporterIFCUtils.GetTransformForDoorOrWindow(currElem, famSymbol, FlippedX, FlippedY);

            IList <Curve> origArcs = GeometryUtil.Get2DArcOrLineFromSymbol(currElem, allCurveType: false, inclArc: true);

            if (origArcs == null || (origArcs.Count == 0))
            {
                return("NOTDEFINED");
            }

            BoundingBoxXYZ doorBB = GetBoundingBoxFromSolids(currElem);
            XYZ            bbMin  = doorWindowTrf.OfPoint(doorBB.Min);
            XYZ            bbMax  = doorWindowTrf.OfPoint(doorBB.Max);

            // Reorganize the bbox min and max after transform
            double xmin = bbMin.X, xmax = bbMax.X, ymin = bbMin.Y, ymax = bbMax.Y, zmin = bbMin.Z, zmax = bbMax.Z;

            if (bbMin.X > bbMax.X)
            {
                xmin = bbMax.X;
                xmax = bbMin.X;
            }
            if (bbMin.Y > bbMax.Y)
            {
                ymin = bbMax.Y;
                ymax = bbMin.Y;
            }
            if (bbMin.Z > bbMax.Z)
            {
                zmin = bbMax.Z;
                zmax = bbMin.Z;
            }
            bbMin = new XYZ(xmin - tolForArcCenter, ymin - tolForArcCenter, zmin - tolForArcCenter);
            bbMax = new XYZ(xmax + tolForArcCenter, ymax + tolForArcCenter, zmax + tolForArcCenter);

            IList <XYZ>        arcCenterLocations = new List <XYZ>();
            SortedSet <double> arcRadii = new SortedSet <double>();

            foreach (Arc arc in origArcs)
            {
                Arc trfArc = arc.CreateTransformed(doorWindowTrf) as Arc;

                // Filter only Arcs that is on XY plane and at the Z=0 of the Door/Window transform
                if (!(MathUtil.IsAlmostEqual(Math.Abs(trfArc.Normal.Z), 1.0) /*&& MathUtil.IsAlmostEqual(Math.Abs(trfArc.Center.Z), Math.Abs(doorWindowTrf.Origin.Z))*/))
                {
                    continue;
                }

                // Filter only Arcs that have center within the bounding box
                if (trfArc.Center.X > bbMax.X || trfArc.Center.X < bbMin.X || trfArc.Center.Y > bbMax.Y || trfArc.Center.Y < bbMin.Y)
                {
                    continue;
                }

                if (!trfArc.IsBound)
                {
                    fullCircleCount++;
                }
                else
                {
                    double angleOffOfXY = 0;
                    XYZ    v1           = CorrectNearlyZeroValueToZero((trfArc.GetEndPoint(0) - trfArc.Center).Normalize());
                    XYZ    v2           = CorrectNearlyZeroValueToZero((trfArc.GetEndPoint(1) - trfArc.Center).Normalize());
                    angleOffOfXY = Math.Acos(v1.DotProduct(v2));

                    if ((Math.Abs(angleOffOfXY) > (60.0 / 180.0) * Math.PI && Math.Abs(angleOffOfXY) < (240.0 / 180.0) * Math.PI) &&
                        ((v1.Y > 0.0 && v2.Y < 0.0) || (v1.Y < 0.0 && v2.Y > 0.0)))       // Consider the opening swing between -30 to +30 up to -120 to +120 degree, where Y axes must be at the opposite sides
                    {
                        if (trfArc.Center.X >= -tolForArcCenter && trfArc.Center.X <= tolForArcCenter)
                        {
                            leftHalfCircleCount++;
                        }
                        else
                        {
                            rightHalfCircleCount++;
                        }
                    }
                    else if ((Math.Abs(angleOffOfXY) > (30.0 / 180.0) * Math.PI && Math.Abs(angleOffOfXY) < (170.0 / 180.0) * Math.PI) &&
                             (MathUtil.IsAlmostEqual(Math.Abs(v1.X), 1.0, allowance) || MathUtil.IsAlmostEqual(Math.Abs(v2.X), 1.0, allowance)))  // Consider the opening swing between 30 to 170 degree, beginning at X axis
                    {
                        XYZ yDir;
                        if (MathUtil.IsAlmostEqual(Math.Abs(v1.Y), Math.Abs(Math.Sin(angleOffOfXY)), 0.01))
                        {
                            yDir = v1;
                        }
                        else
                        {
                            yDir = v2;
                        }

                        // if the Normal is pointing to -Z, it is flipped. Flip the Y if it is
                        if (MathUtil.IsAlmostEqual(trfArc.Normal.Z, -1.0))
                        {
                            yDir = yDir.Negate();
                        }

                        // Check the center location in the X-direction to determine LEFT/RIGHT
                        if (trfArc.Center.X >= -tolForArcCenter && trfArc.Center.X <= tolForArcCenter)
                        {
                            // on the LEFT
                            if ((yDir.Y > 0.0 && trfArc.YDirection.Y > 0.0) || (yDir.Y < 0.0 && trfArc.YDirection.Y < 0.0))
                            {
                                leftPosYArcCount++;
                            }
                            else if ((yDir.Y > 0.0 && trfArc.YDirection.Y < 0.0) || (yDir.Y < 0.0 && trfArc.YDirection.Y > 0.0))
                            {
                                leftNegYArcCount++;
                            }
                            else
                            {
                                continue;
                            }
                        }
                        else
                        {
                            // on the RIGHT
                            if ((yDir.Y > 0.0 && trfArc.YDirection.Y > 0.0) || (yDir.Y < 0.0 && trfArc.YDirection.Y < 0.0))
                            {
                                rightPosYArcCount++;
                            }
                            else if ((yDir.Y > 0.0 && trfArc.YDirection.Y < 0.0) || (yDir.Y < 0.0 && trfArc.YDirection.Y > 0.0))
                            {
                                rightNegYArcCount++;
                            }
                            else
                            {
                                continue;
                            }
                        }
                    }
                    else
                    {
                        continue;
                    }

                    // Collect all distinct Arc Center if it is counted as the door opening, to ensure that for cases that there are more than 2 leafs, it is not worngly labelled
                    bool foundExisting = false;
                    foreach (XYZ existingCenter in arcCenterLocations)
                    {
                        if ((trfArc.Center.X > existingCenter.X - tolForArcCenter) && (trfArc.Center.X <= existingCenter.X + tolForArcCenter) &&
                            (trfArc.Center.Y > existingCenter.Y - tolForArcCenter) && (trfArc.Center.Y <= existingCenter.Y + tolForArcCenter))
                        {
                            foundExisting = true;
                            break;
                        }
                    }
                    if (!foundExisting)
                    {
                        arcCenterLocations.Add(trfArc.Center);
                        arcRadii.Add(trfArc.Radius);
                    }
                }
            }

            // When only full circle(s) exists
            if (fullCircleCount > 0 &&
                rightHalfCircleCount == 0 && leftHalfCircleCount == 0 && leftPosYArcCount == 0 && leftNegYArcCount == 0 && rightPosYArcCount == 0 && rightNegYArcCount == 0)
            {
                return("REVOLVING");
            }

            // There are more than 2 arc centers, no IFC Door operation type fits this, return NOTDEFINED
            if (arcCenterLocations.Count > 2)
            {
                return("NOTDEFINED");
            }

            // When half circle arc(s) exists
            if (leftHalfCircleCount > 0 && fullCircleCount == 0)
            {
                if (rightHalfCircleCount == 0 && leftPosYArcCount == 0 && leftNegYArcCount == 0 && rightPosYArcCount == 0 && rightNegYArcCount == 0)
                {
                    return("DOUBLE_SWING_LEFT");
                }

                if ((rightHalfCircleCount > 0 || (rightPosYArcCount > 0 && rightNegYArcCount > 0)) && leftPosYArcCount == 0 && leftNegYArcCount == 0)
                {
                    return("DOUBLE_DOOR_DOUBLE_SWING");
                }
            }

            if (rightHalfCircleCount > 0 && fullCircleCount == 0)
            {
                if (leftHalfCircleCount == 0 && leftPosYArcCount == 0 && leftNegYArcCount == 0 && rightPosYArcCount == 0 && rightNegYArcCount == 0)
                {
                    return("DOUBLE_SWING_RIGHT");
                }

                if ((leftHalfCircleCount > 0 || (leftPosYArcCount > 0 && leftNegYArcCount > 0)) && rightPosYArcCount == 0 && rightNegYArcCount == 0)
                {
                    return("DOUBLE_DOOR_DOUBLE_SWING");
                }
            }

            // When only 90-degree arc(s) exists
            if (leftPosYArcCount > 0 &&
                fullCircleCount == 0 && rightHalfCircleCount == 0 && leftHalfCircleCount == 0 && leftNegYArcCount == 0 && rightPosYArcCount == 0 && rightNegYArcCount == 0)
            {
                // if the arc is less than 50%of the boundingbox, treat this to be a door with partially fixed panel
                if (arcRadii.Max < (bbMax.X - bbMin.X) * 0.5)
                {
                    if (ExporterCacheManager.ExportOptionsCache.ExportAsOlderThanIFC4)
                    {
                        return("NOTDEFINED");
                    }
                    else
                    {
                        return("SWING_FIXED_LEFT");
                    }
                }
                else
                {
                    return("SINGLE_SWING_LEFT");
                }
            }

            if (rightPosYArcCount > 0 &&
                fullCircleCount == 0 && rightHalfCircleCount == 0 && leftHalfCircleCount == 0 && leftNegYArcCount == 0 && leftPosYArcCount == 0 && rightNegYArcCount == 0)
            {
                // if the arc is less than 50%of the boundingbox, treat this to be a door with partially fixed panel
                if (arcRadii.Max < (bbMax.X - bbMin.X) * 0.5)
                {
                    if (ExporterCacheManager.ExportOptionsCache.ExportAsOlderThanIFC4)
                    {
                        return("NOTDEFINED");
                    }
                    else
                    {
                        return("SWING_FIXED_RIGHT");
                    }
                }
                else
                {
                    return("SINGLE_SWING_RIGHT");
                }
            }

            if (leftPosYArcCount > 0 && leftNegYArcCount > 0 &&
                fullCircleCount == 0 && rightHalfCircleCount == 0 && leftHalfCircleCount == 0 && rightPosYArcCount == 0 && rightNegYArcCount == 0)
            {
                return("DOUBLE_SWING_LEFT");
            }

            if (rightPosYArcCount > 0 && rightNegYArcCount > 0 &&
                fullCircleCount == 0 && rightHalfCircleCount == 0 && leftHalfCircleCount == 0 && leftNegYArcCount == 0 && leftPosYArcCount == 0)
            {
                return("DOUBLE_SWING_RIGHT");
            }

            if (leftPosYArcCount > 0 && rightPosYArcCount > 0 &&
                fullCircleCount == 0 && rightHalfCircleCount == 0 && leftHalfCircleCount == 0 && leftNegYArcCount == 0 && rightNegYArcCount == 0)
            {
                return("DOUBLE_DOOR_SINGLE_SWING");
            }

            if (leftPosYArcCount > 0 && rightPosYArcCount > 0 && leftNegYArcCount > 0 && rightNegYArcCount > 0 &&
                fullCircleCount == 0 && rightHalfCircleCount == 0 && leftHalfCircleCount == 0)
            {
                return("DOUBLE_DOOR_DOUBLE_SWING");
            }

            if (leftPosYArcCount > 0 && rightNegYArcCount > 0 &&
                fullCircleCount == 0 && rightHalfCircleCount == 0 && leftHalfCircleCount == 0 && leftNegYArcCount == 0 && rightPosYArcCount == 0)
            {
                return("DOUBLE_DOOR_SINGLE_SWING_OPPOSITE_RIGHT");
            }

            if (leftNegYArcCount > 0 && rightPosYArcCount > 0 &&
                fullCircleCount == 0 && rightHalfCircleCount == 0 && leftHalfCircleCount == 0 && leftPosYArcCount == 0 && rightNegYArcCount == 0)
            {
                return("DOUBLE_DOOR_SINGLE_SWING_OPPOSITE_LEFT");
            }

            return("NOTDEFINED");
        }