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(); }
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); }