Beispiel #1
0
        public void UpdatePatternDefinition()
        {
            if (fillPattern == null)
            {
                SCaddinsApp.WindowManager.ShowMessageBox("Null Hatch");
                return;
            }
            StringBuilder s = new StringBuilder();

            foreach (var p in fillPattern.GetFillGrids())
            {
                double angle = p.Angle.ToDeg();
                s.Append(string.Format(System.Globalization.CultureInfo.InvariantCulture, "{0},\t{1},\t{2},\t{3},\t{4}", angle, p.Origin.U.ToMM(), p.Origin.V.ToMM(), p.Shift.ToMM(), p.Offset.ToMM()));
                foreach (double d in p.GetSegments())
                {
                    s.Append(string.Format(System.Globalization.CultureInfo.InvariantCulture, ",\t{0}", d.ToMM()));
                }
                s.Append(Environment.NewLine);
            }
            definition = s.ToString();
        }
Beispiel #2
0
        private static void DrawFillPattern(Graphics g, FillPattern fillPattern)
        {
            Stopwatch sw = Stopwatch.StartNew();

            if (fillPattern == null)
            {
                return;
            }

            float matrixScale = 1000;

            try
            {
                var width = 30;

                var height = 30;

                var rect = new System.Drawing.Rectangle(0, 0, (int)width, (int)height);

                var rect_border = new System.Drawing.Rectangle(0, 0, (int)width - 1, (int)height - 1);
                Pen myPen       = new Pen(System.Drawing.Color.FromArgb(0, 255, 220), 1);

                g.DrawRectangle(myPen, rect_border);

                var centerX = (rect.Left + rect.Left + rect.Width) / 2;

                var centerY = (rect.Top + rect.Top + rect.Height) / 2;

                g.TranslateTransform(centerX, centerY);

                var rectF = new System.Drawing.Rectangle(-1, -1, 2, 2);

                g.FillRectangle(System.Drawing.Brushes.Transparent, rectF);

                g.ResetTransform();

                var fillGrids = fillPattern.GetFillGrids();

                foreach (var fillGrid in fillGrids)
                {
                    var degreeAngle = (float)fillGrid.Angle * 180 / Math.PI;

                    var pen = new System.Drawing.Pen(System.Drawing.Color.FromArgb(0, 255, 220))
                    {
                        Width = 1f / matrixScale
                    };

                    float dashLength = 1;

                    var segments = fillGrid.GetSegments();

                    if (segments.Count > 0)
                    {
                        pen.DashPattern = segments
                                          .Select(s => Math.Max(float.Epsilon, Convert.ToSingle(s)))
                                          .ToArray();

                        dashLength = pen.DashPattern.Sum();
                    }

                    g.ResetTransform();

                    var rotateMatrix = new System.Drawing.Drawing2D.Matrix();
                    rotateMatrix.Rotate((float)degreeAngle);

                    var matrix = new System.Drawing.Drawing2D.Matrix(1, 0, 0, -1,
                                                                     centerX, centerY);

                    matrix.Scale(matrixScale, matrixScale);

                    matrix.Translate((float)fillGrid.Origin.U,
                                     (float)fillGrid.Origin.V);

                    var backMatrix = matrix.Clone();
                    backMatrix.Multiply(rotateMatrix);
                    matrix.Multiply(rotateMatrix);

                    var offset = (-10) * dashLength;
                    matrix.Translate(offset, 0);
                    backMatrix.Translate(offset, 0);

                    bool   moving_forward = true;
                    bool   moving_back    = true;
                    int    safety         = 500;
                    double alternator     = 0;
                    while (moving_forward || moving_back) // draw segments shifting and offsetting each time
                    {
                        var rectF1 = new RectangleF(-2 / matrixScale, -2 / matrixScale, 4 / matrixScale, 4 / matrixScale);

                        if (moving_forward && LineIntersectsRect(matrix, rect))
                        {
                            g.Transform = matrix;
                            g.DrawLine(pen, new PointF(0, 0), new PointF(100, 0));
                        }
                        else
                        {
                            moving_forward = false;
                        }

                        if (moving_back && LineIntersectsRect(backMatrix, rect))
                        {
                            g.Transform = backMatrix;
                            g.DrawLine(pen, new PointF(0, 0), new PointF(100, 0));
                        }
                        else
                        {
                            moving_back = false;
                        }

                        if (safety == 0)
                        {
                            break;
                        }
                        else
                        {
                            --safety;
                        }

                        matrix.Translate((float)fillGrid.Shift, (float)fillGrid.Offset);
                        backMatrix.Translate(-(float)fillGrid.Shift, -(float)fillGrid.Offset);

                        alternator += fillGrid.Shift;
                        if (Math.Abs(alternator) > Math.Abs(offset))
                        {
                            matrix.Translate(offset, 0);
                            backMatrix.Translate(offset, 0);
                            alternator = 0d;
                        }
                    }
                }

                sw.Stop();
                g.ResetTransform();

                Pen p = new Pen(System.Drawing.Color.Teal);
                p.Width = 1f / matrixScale;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
        /***************************************************/

        public static List <BH.oM.Geometry.Line> CeilingPattern(this Material revitMaterial, PlanarSurface surface, RevitSettings settings, XYZ origin = null, double angle = 0)
        {
            surface = surface.Rotate(BH.oM.Geometry.Point.Origin, Vector.ZAxis, -angle);
            BoundingBox box = surface.IBounds();

            origin = Transform.CreateRotation(XYZ.BasisZ, -angle).OfPoint(origin);

            double z            = surface.ExternalBoundary.IControlPoints().Max(x => x.Z);
            double yLength      = (box.Max.Y - box.Min.Y) / 2;
            double xLength      = (box.Max.X - box.Min.X) / 2;
            double maxBoxLength = box.Min.Distance(box.Max);

            BH.oM.Geometry.Line leftLine = new oM.Geometry.Line
            {
                Start = new oM.Geometry.Point {
                    X = box.Min.X, Y = box.Min.Y, Z = z
                },
                End = new oM.Geometry.Point {
                    X = box.Min.X, Y = box.Max.Y, Z = z
                },
            };

            BH.oM.Geometry.Line rightLine = new oM.Geometry.Line
            {
                Start = new oM.Geometry.Point {
                    X = box.Max.X, Y = box.Min.Y, Z = z
                },
                End = new oM.Geometry.Point {
                    X = box.Max.X, Y = box.Max.Y, Z = z
                },
            };

            List <BH.oM.Geometry.Line> boundarySegments = surface.ExternalBoundary.ICollapseToPolyline(settings.AngleTolerance).SubParts().ToList();

            List <BH.oM.Geometry.Line> patterns           = new List <BH.oM.Geometry.Line>();
            FillPatternElement         fillPatternElement = null;

#if (REVIT2020 || REVIT2021)
            fillPatternElement = revitMaterial.Document.GetElement(revitMaterial.SurfaceForegroundPatternId) as FillPatternElement;
#else
            fillPatternElement = revitMaterial.Document.GetElement(revitMaterial.SurfacePatternId) as FillPatternElement;
#endif

            if (fillPatternElement != null)
            {
                FillPattern fillPattern = fillPatternElement.GetFillPattern();
                if (fillPattern == null || fillPattern.IsSolidFill)
                {
                    return(new List <oM.Geometry.Line>()); //Skip solid filled patterns
                }
                IList <FillGrid> fillGridList = fillPattern.GetFillGrids();
                foreach (FillGrid grid in fillGridList)
                {
                    double offset = grid.Offset.ToSI(UnitType.UT_Length);

                    double currentY = ((int)((box.Min.Y - yLength) / offset)) * offset;
                    double currentX = ((int)((box.Min.X - xLength) / offset)) * offset;

                    double minNum = currentX;
                    double maxNum = (box.Max.X + xLength);

                    if (grid.Angle.ToSI(UnitType.UT_Angle) > settings.AngleTolerance)
                    {
                        minNum = currentY;
                        maxNum = (box.Max.Y + yLength);
                    }

                    if (origin != null)
                    {
                        if (grid.Angle.ToSI(UnitType.UT_Angle) > settings.AngleTolerance)
                        {
                            minNum += (origin.Y % grid.Offset).ToSI(UnitType.UT_Length);
                        }
                        else
                        {
                            minNum += (origin.X % grid.Offset).ToSI(UnitType.UT_Length);
                        }
                    }

                    while ((minNum + offset) < maxNum)
                    {
                        BH.oM.Geometry.Point pt = new oM.Geometry.Point {
                            X = minNum + offset, Y = box.Min.Y, Z = z
                        };
                        BH.oM.Geometry.Point pt2 = new oM.Geometry.Point {
                            X = minNum + offset, Y = box.Max.Y, Z = z
                        };

                        BH.oM.Geometry.Line pline = new oM.Geometry.Line {
                            Start = pt, End = pt2
                        };

                        if (grid.Angle.ToSI(UnitType.UT_Angle) > settings.AngleTolerance)
                        {
                            BH.oM.Geometry.Point rotatePt = pline.Centroid();
                            pline = pline.Rotate(rotatePt, Vector.ZAxis, grid.Angle.ToSI(UnitType.UT_Angle));

                            pline.Start.Y = minNum + offset;
                            pline.End.Y   = minNum + offset;

                            BH.oM.Geometry.Point intersect = pline.LineIntersection(leftLine, true);
                            if (intersect != null)
                            {
                                pline.Start = intersect;
                            }

                            intersect = pline.LineIntersection(rightLine, true);
                            if (intersect != null)
                            {
                                pline.End = intersect;
                            }

                            Vector v1 = pline.End - pline.Start; //From start TO end
                            v1 *= maxBoxLength;
                            Vector v2 = pline.Start - pline.End; //From end TO start
                            v2 *= maxBoxLength;

                            pline.Start = pline.Start.Translate(v2);
                            pline.End   = pline.End.Translate(v1);
                        }

                        List <BH.oM.Geometry.Point> intersections = new List <oM.Geometry.Point>();
                        foreach (BH.oM.Geometry.Line l in boundarySegments)
                        {
                            BH.oM.Geometry.Point p = pline.LineIntersection(l);
                            if (p != null)
                            {
                                intersections.Add(p);
                            }
                        }

                        List <BH.oM.Geometry.Line> lines = new List <oM.Geometry.Line>();

                        if (intersections.Count > 0)
                        {
                            lines = pline.SplitAtPoints(intersections);
                        }
                        else
                        {
                            lines.Add(pline);
                        }

                        foreach (BH.oM.Geometry.Line l in lines)
                        {
                            List <BH.oM.Geometry.Point> pts = l.ControlPoints();
                            pts.Add(l.Centroid());

                            if (surface.ExternalBoundary.IIsContaining(pts, true))
                            {
                                patterns.Add(l.Rotate(BH.oM.Geometry.Point.Origin, Vector.ZAxis, angle));
                            }
                        }

                        minNum += offset;
                    }
                }
            }

            patterns.AddRange(boundarySegments.Select(x => x.Rotate(BH.oM.Geometry.Point.Origin, Vector.ZAxis, angle))); //Close off the ceiling pattern for its own use

            return(patterns);
        }
        /***************************************************/
        /****              Private methods              ****/
        /***************************************************/

        private static XYZ CeilingPatternAlignment(this Ceiling ceiling, Material material, RevitSettings settings, out double rotation)
        {
            rotation = 0;
            if (ceiling == null || material == null)
            {
                return(null);
            }

            Document doc = ceiling.Document;

            FillPatternElement fillPatternElement;

#if (REVIT2020 || REVIT2021)
            fillPatternElement = doc.GetElement(material.SurfaceForegroundPatternId) as FillPatternElement;
#else
            fillPatternElement = doc.GetElement(material.SurfacePatternId) as FillPatternElement;
#endif

            FillPattern fp = fillPatternElement?.GetFillPattern();
            if (fp == null || fp.GridCount != 2)
            {
                return(null);
            }

            XYZ result = null;
            settings = settings.DefaultIfNull();

            Options o = new Options();
            o.ComputeReferences = true;
            Document          hostDoc       = doc.IsLinked ? doc.HostDocument() : doc;
            RevitLinkInstance linkInstance  = doc.IsLinked ? doc.LinkInstance() : null;
            Transform         linkTransform = linkInstance == null ? Transform.Identity : linkInstance.GetTotalTransform();

            foreach (GeometryObject go in ceiling.get_Geometry(o))
            {
                if (go is Solid)
                {
                    foreach (Autodesk.Revit.DB.Face f in ((Solid)go).Faces)
                    {
                        PlanarFace pf = f as PlanarFace;
                        if (pf == null)
                        {
                            continue;
                        }

                        if (1 + pf.FaceNormal.DotProduct(XYZ.BasisZ) > settings.AngleTolerance)
                        {
                            continue;
                        }

                        Reference faceRef = f.Reference;
                        if (doc.IsLinked)
                        {
                            faceRef = faceRef.CreateLinkReference(linkInstance).PrepareForLinkDimensioning(hostDoc);
                        }

                        string stableRef = faceRef.ConvertToStableRepresentation(hostDoc);

                        ReferenceArray horR = new ReferenceArray();
                        horR.Append(Reference.ParseFromStableRepresentation(hostDoc, stableRef + "/2"));
                        horR.Append(Reference.ParseFromStableRepresentation(hostDoc, stableRef + "/" + (2 + fp.GridCount * 2).ToString()));

                        ReferenceArray verR = new ReferenceArray();
                        verR.Append(Reference.ParseFromStableRepresentation(hostDoc, stableRef + "/1"));
                        verR.Append(Reference.ParseFromStableRepresentation(hostDoc, stableRef + "/" + (1 + fp.GridCount * 2).ToString()));

                        using (Transaction t = new Transaction(hostDoc, "temp dim"))
                        {
                            t.Start();
                            Dimension horDim = hostDoc.Create.NewDimension(hostDoc.ActiveView, Autodesk.Revit.DB.Line.CreateBound(XYZ.Zero, pf.XVector), horR);
                            Dimension verDim = hostDoc.Create.NewDimension(hostDoc.ActiveView, Autodesk.Revit.DB.Line.CreateBound(XYZ.Zero, pf.YVector), verR);
                            ElementTransformUtils.MoveElement(hostDoc, horDim.Id, XYZ.BasisX);
                            ElementTransformUtils.MoveElement(hostDoc, verDim.Id, XYZ.BasisX);

                            rotation  = -(horDim.Curve as Autodesk.Revit.DB.Line).Direction.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ);
                            rotation += linkTransform.BasisX.AngleOnPlaneTo(XYZ.BasisX, XYZ.BasisZ);
                            Transform tr = Transform.CreateRotation(XYZ.BasisZ, rotation);

                            double x = tr.Inverse.OfPoint(linkTransform.Inverse.OfPoint(horDim.Origin)).X;
                            double y = tr.Inverse.OfPoint(linkTransform.Inverse.OfPoint(verDim.Origin)).Y;
                            t.RollBack();

                            foreach (FillGrid fg in fp.GetFillGrids())
                            {
                                if (fg.Angle.ToSI(UnitType.UT_Angle) > settings.AngleTolerance)
                                {
                                    y += fg.Offset * 0.5;
                                }
                                else
                                {
                                    x += fg.Offset * 0.5;
                                }
                            }

                            result = tr.OfPoint(new XYZ(x, y, 0));
                            break;
                        }
                    }
                }
            }

            return(result);
        }