public static void PlaceDoorsAt(string schemeName) { string inputLayerPath = schemeName + "::EJLT Shapes"; string outputLayerPath = schemeName + "::Doors"; UnitSystem currentDocUnits = RhinoDoc.ActiveDoc.ModelUnitSystem; double unitSystemScaler = RhinoMath.UnitScale(UnitSystem.Feet, currentDocUnits); double doorW = 2.5 * unitSystemScaler; double doorH = 0.2 * unitSystemScaler; // get curves List <int> layerIndexs; List <Curve> curves = LayerHelper.GetCurvesFromChild(inputLayerPath, out layerIndexs); // explode curves List <Polyline> polies = new List <Polyline>(); List <Line[]> exploded = new List <Line[]>(); foreach (Curve c in curves) { Polyline poly; c.TryGetPolyline(out poly); polies.Add(poly); exploded.Add(poly.GetSegments()); } List <Point3d> centers = new List <Point3d>(); List <bool> vertical = new List <bool>(); // find overlapping curves, find center, find direction of lines for (int i = 0; i < polies.Count; i++) { foreach (Line line in exploded[i]) { for (int j = 0; j < polies.Count; j++) { if (i == j) { continue; // skip intersection check with current rectangle } foreach (Line otherline in exploded[j]) { Curve c1 = line.ToNurbsCurve(); Curve c2 = otherline.ToNurbsCurve(); // get all intersections var intersects = Intersection.CurveCurve(c1, c2, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance, 0.1); if (intersects != null && intersects.Count > 0) { foreach (var inter in intersects) { if (inter.IsOverlap) // a overlap found { double length = inter.OverlapA.Length * c1.GetLength(); if (length > 3.5 * unitSystemScaler) // overlap is long enough { Point3d mid = c1.PointAt(inter.OverlapA.Mid); double mindis = 10000.0; foreach (Point3d oldpt in centers) { double distance = mid.DistanceTo(oldpt); if (distance < mindis) { mindis = distance; } } if (mindis > 1.0) // no duplicates { centers.Add(c1.PointAt(inter.OverlapA.Mid)); if (c1.PointAt(0).X == c1.PointAt(1).X) { vertical.Add(true); } else { vertical.Add(false); } } } } } } } } } } // draws rectangle for (int i = 0; i < centers.Count; i++) { if (vertical[i]) { Point3d corner = new Point3d(centers[i].X - doorH / 2, centers[i].Y - doorW / 2, 0.0); Rectangle3d rec = new Rectangle3d(new Plane(corner, Vector3d.ZAxis), doorH, doorW); LayerHelper.BakeObjectToLayer(rec.ToPolyline().ToPolylineCurve(), "Doors", schemeName); } else { Point3d corner = new Point3d(centers[i].X - doorW / 2, centers[i].Y - doorH / 2, 0.0); Rectangle3d rec = new Rectangle3d(new Plane(corner, Vector3d.ZAxis), doorW, doorH); LayerHelper.BakeObjectToLayer(rec.ToPolyline().ToPolylineCurve(), "Doors", schemeName); } } Rhino.RhinoDoc.ActiveDoc.Views.Redraw(); }
public static void Make3d(string schemeName) { string inputLayerPath = schemeName + "::EJLT Shapes"; string outputLayerPath = schemeName + "::Walls"; string doorsLayerPath = schemeName + "::Doors"; List <int> layerIndexs; List <Curve> curves = LayerHelper.GetCurvesFromChild(inputLayerPath, out layerIndexs); List <Curve> doors = LayerHelper.GetCurvesFrom(doorsLayerPath); List <LineCurve> afterCut = new List <LineCurve>(); List <Line> exploded = new List <Line>(); foreach (Curve c in curves) { Polyline poly; c.TryGetPolyline(out poly); exploded.AddRange(poly.GetSegments()); } List <Line> lineSegDoor = new List <Line>(); List <List <LineCurve> > doorsPerSeg = new List <List <LineCurve> >(); foreach (Line lineSeg in exploded) { List <LineCurve> doorsThisSeg = new List <LineCurve>(); foreach (Curve door in doors) { CurveIntersections inter = Intersection.CurveLine(door, lineSeg, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance, 0.0); if (inter.Count == 2) { LineCurve l1; Point3d p1 = inter.First().PointA; Point3d p2 = inter[1].PointA; l1 = new LineCurve(p1, p2); doorsThisSeg.Add(l1); } } if (doorsThisSeg.Count > 0) { lineSegDoor.Add(lineSeg); doorsPerSeg.Add(doorsThisSeg); } else { // no intersection, add to after cut afterCut.Add(new LineCurve(lineSeg)); } } for (int i = 0; i < lineSegDoor.Count; i++) { // points from all intersection points List <Point3d> intersectionPts = new List <Point3d>(); intersectionPts.Add(lineSegDoor[i].From); intersectionPts.Add(lineSegDoor[i].To); foreach (LineCurve doorLine in doorsPerSeg[i]) { intersectionPts.Add(doorLine.PointAtStart); intersectionPts.Add(doorLine.PointAtEnd); } List <Point3d> sortedPoints = intersectionPts.OrderBy(pnt => pnt.Y).ThenBy(pnt => pnt.X).ToList(); // construct line segments for (int pi = 0; pi < sortedPoints.Count; pi = pi + 2) { LineCurve cuttedSegment = new LineCurve(sortedPoints[pi], sortedPoints[pi + 1]); bool indoor = false; foreach (Curve door in doors) { if (door.Contains(cuttedSegment.PointAt(0.5), Plane.WorldXY, Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance) == PointContainment.Inside) { indoor = true; break; } } if (!indoor) { afterCut.Add(cuttedSegment); } } } UnitSystem currentDocUnits = RhinoDoc.ActiveDoc.ModelUnitSystem; double unitSystemScaler = RhinoMath.UnitScale(UnitSystem.Feet, currentDocUnits); foreach (LineCurve wallLine in afterCut) { LayerHelper.BakeObjectToLayer(Extrusion.Create(wallLine, 8 * unitSystemScaler, false).ToBrep(), "Walls", schemeName); } Rhino.RhinoDoc.ActiveDoc.Views.Redraw(); }
private void InitializeComponent() { #region COMMAND SETUP OpenWebPage = new RelayCommand <object>(obj => { System.Diagnostics.Process.Start("https://ganplan.emptybox.io/"); message.Text = "After Selecting a Scheme on the web, bring it into Rhino with an API call. "; }); CallAPI = new RelayCommand <object>(obj => { WebCallManager myFooBar = new WebCallManager(); myFooBar.QueryMLServer(schemeNameBox.Text + "::Rectangles"); LayerHelper.CheckLayerStructure((schemeNameBox.Text + "::Rectangles")); LayerHelper.CheckLayerStructure((schemeNameBox.Text + "::EJLT Shapes")); message.Text = "Adjust the rectangles to match your desired area. "; }); CalcRecArea = new RelayCommand <object>(obj => { UpdateArea(schemeNameBox.Text + "::Rectangles", area); message.Text = "Cut out specific shapes of your rooms. "; }); MakeEltjShapes = new RelayCommand <object>(obj => { IntersectNow(schemeNameBox.Text + "::Rectangles", schemeNameBox.Text + "::EJLT Shapes"); }); UpdateEltjShapeAreas = new RelayCommand <object>(obj => { UpdateArea(schemeNameBox.Text + "::EJLT Shapes", area); }); PlaceDoors = new RelayCommand <object>(obj => { Doors.PlaceDoorsAt(schemeNameBox.Text); }); Make3DGeometry = new RelayCommand <object>(obj => { Doors.Make3d(schemeNameBox.Text); }); #endregion #region Button Setup OpenWebPageButton = new Button { Text = Rhino.UI.LOC.STR("Open Web Page"), Command = OpenWebPage }; CallAPIButton = new Button { Text = Rhino.UI.LOC.STR("Call API for selected Scheme"), Command = CallAPI }; CalcRecAreaButton = new Button { Text = Rhino.UI.LOC.STR("Calc Rectangle Area"), Command = CalcRecArea }; MakeEltjShapesButton = new Button { Text = Rhino.UI.LOC.STR("Cut Shapes"), Command = MakeEltjShapes }; UpdateEltjShapeAreasButton = new Button { Text = Rhino.UI.LOC.STR("Calc Shape Area"), Command = UpdateEltjShapeAreas }; PlaceDoorsButton = new Button { Text = Rhino.UI.LOC.STR("Place Some Doors"), Command = PlaceDoors }; Make3DGeometryButton = new Button { Text = Rhino.UI.LOC.STR("See it in 3D"), Command = Make3DGeometry }; #endregion #region message = new Label(); message.Text = "Open our web tool to start!"; message.Height = 30; message.TextColor = new Eto.Drawing.Color(0, 0, 1); warning = new Label(); warning.Text = ""; warning.TextColor = new Eto.Drawing.Color(1, .2f, 0); warning.Font = new Eto.Drawing.Font(Eto.Drawing.SystemFont.Bold, 11); area = new Label(); area.Text = ""; area.Font = new Eto.Drawing.Font(Eto.Drawing.SystemFont.Bold, 11); urlInputBox = new TextBox(); urlInputBox.Text = "paste in URL"; schemeNameBox = new TextBox(); schemeNameBox.Text = "Scheme1"; #endregion Content = new TableLayout { Padding = 0, Spacing = new Size(4, 4), Rows = { new Label { Text = "GanPlan", Font = new Eto.Drawing.Font(Eto.Drawing.SystemFont.Bold, 13) }, message, null, OpenWebPageButton, null, new Label { Text = "Name your Scheme: " }, schemeNameBox, CallAPIButton, null, area, CalcRecAreaButton, MakeEltjShapesButton, UpdateEltjShapeAreasButton, null, PlaceDoorsButton, null, Make3DGeometryButton, null, } }; }