/***************************************************/ private static PolyCurve Fillet(this ICurve curve1, ICurve curve2, bool tangentExtensions, bool keepCurve1StartPoint, bool keepCurve2StartPoint, double tolerance = Tolerance.Distance) { //TODO: //Write a proper fillet method, test and make it public if (!((curve1 is Line || curve1 is Arc) && (curve2 is Line || curve2 is Arc))) //for now works only with combinations of lines and arcs { Reflection.Compute.RecordError("Private method fillet is implemented only for PolyCurves consisting of Lines or Arcs."); return(null); } List <PolyCurve> joinCurves = Compute.IJoin(new List <ICurve> { curve1, curve2 }, tolerance).ToList(); if (joinCurves.Count == 1) { return(joinCurves[0]); } List <ICurve> resultCurves = new List <ICurve>(); bool C1SP = keepCurve1StartPoint; bool C2SP = keepCurve2StartPoint; List <Point> intersections = curve1.ICurveIntersections(curve2, tolerance); if (intersections.Count > 2) { Reflection.Compute.RecordError("Invalid number of intersections between curves. Two lines/arcs can have no more than two intersections."); } else if (intersections.Count == 2 || intersections.Count == 1) { Point intersection = intersections[0]; if (intersections.Count == 2) { double maxdist = double.MaxValue; if (C1SP) { foreach (Point p in intersections) { double dist = p.SquareDistance(curve1.IStartPoint()); if (dist < maxdist) { intersection = p; maxdist = dist; } } } else { foreach (Point p in intersections) { double dist = p.SquareDistance(curve1.IEndPoint()); if (dist < maxdist) { intersection = p; maxdist = dist; } } } } else { intersection = intersections[0]; } if (C1SP && C2SP) { resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[1] = resultCurves[1].IFlip(); } else if (C1SP && !C2SP) { resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); } else if (!C1SP && C2SP) { resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); resultCurves[1] = resultCurves[1].IFlip(); } else { resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); } } else { if (curve1 is Line && curve2 is Line) { Point intersection = (curve1 as Line).LineIntersection(curve2 as Line, true, tolerance); if (C1SP && C2SP) { if ((curve1.IStartPoint().Distance((curve2 as Line), true) < curve1.IEndPoint().Distance((curve2 as Line), true) && !intersection.IIsOnCurve(curve1)) || (curve2.IStartPoint().Distance((curve1 as Line), true) < curve2.IEndPoint().Distance((curve1 as Line), true) && !intersection.IIsOnCurve(curve2))) { Reflection.Compute.RecordWarning("Couldn't provide correct fillet for given input"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[1] = resultCurves[1].IFlip(); } else if (C1SP && !C2SP) { if ((curve1.IStartPoint().Distance((curve2 as Line), true) < curve1.IEndPoint().Distance((curve2 as Line), true) && !intersection.IIsOnCurve(curve1)) || (curve2.IStartPoint().Distance((curve1 as Line), true) > curve2.IEndPoint().Distance((curve1 as Line), true) && !intersection.IIsOnCurve(curve2))) { Reflection.Compute.RecordWarning("Couldn't provide correct fillet for given input"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); } else if (!C1SP && C2SP) { if ((curve1.IStartPoint().Distance((curve2 as Line), true) > curve1.IEndPoint().Distance((curve2 as Line), true) && !intersection.IIsOnCurve(curve1)) || (curve2.IStartPoint().Distance((curve1 as Line), true) < curve2.IEndPoint().Distance((curve1 as Line), true) && !intersection.IIsOnCurve(curve2))) { Reflection.Compute.RecordWarning("Couldn't provide correct fillet for given input"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); resultCurves[1] = resultCurves[1].IFlip(); } else { if ((curve1.IStartPoint().Distance((curve2 as Line), true) > curve1.IEndPoint().Distance((curve2 as Line), true) && !intersection.IIsOnCurve(curve1)) || (curve2.IStartPoint().Distance((curve1 as Line), true) > curve2.IEndPoint().Distance((curve1 as Line), true) && !intersection.IIsOnCurve(curve2))) { Reflection.Compute.RecordWarning("Couldn't provide correct fillet for given input"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); } } else { Point intersection; if (!tangentExtensions) { PolyCurve pCurve1 = new PolyCurve(); PolyCurve pCurve2 = new PolyCurve(); if (curve1 is Arc) { pCurve1.Curves.Add(new Circle { Centre = (curve1 as Arc).Centre(), Normal = (curve1 as Arc).Normal(), Radius = (curve1 as Arc).Radius }); } else { pCurve1.Curves.Add(new Line { Start = (curve1 as Line).Start, End = (curve1 as Line).End, Infinite = true }); } if (curve2 is Arc) { pCurve2.Curves.Add(new Circle { Centre = (curve2 as Arc).Centre(), Normal = (curve2 as Arc).Normal(), Radius = (curve2 as Arc).Radius }); } else { pCurve2.Curves.Add(new Line { Start = (curve2 as Line).Start, End = (curve2 as Line).End, Infinite = true }); } List <Point> curveIntersections = pCurve1.CurveIntersections(pCurve2, tolerance); if (curveIntersections.Count == 0) { Reflection.Compute.RecordError("Curves' extensions do not intersect"); return(null); } if (C1SP && C2SP) { intersection = curveIntersections.ClosestPoint(curve1.IEndPoint()); resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[1] = resultCurves[1].IFlip(); } else if (C1SP && !C2SP) { intersection = curveIntersections.ClosestPoint(curve1.IEndPoint()); resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); } else if (!C1SP && C2SP) { intersection = curveIntersections.ClosestPoint(curve1.IStartPoint()); resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); resultCurves[1] = resultCurves[1].IFlip(); } else { intersection = curveIntersections.ClosestPoint(curve1.IStartPoint()); resultCurves.AddRange(curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); resultCurves[0] = resultCurves[0].IFlip(); } } else { if (C1SP && C2SP) { Line tanLine1 = Create.Line(curve1.IEndPoint(), curve1.IEndDir() / tolerance); tanLine1.Infinite = false; PolyCurve pCurve1 = new PolyCurve { Curves = { curve1, tanLine1 } }; Line tanLine2 = Create.Line(curve2.IEndPoint(), curve2.IEndDir() / tolerance); tanLine2.Infinite = false; PolyCurve pCurve2 = new PolyCurve { Curves = { curve2, tanLine2 } }; List <Point> curveIntersecions = pCurve1.CurveIntersections(pCurve2, tolerance); if (curveIntersecions.Count > 0) { intersection = curveIntersecions.ClosestPoint(curve1.IEndPoint()); } else { Reflection.Compute.RecordWarning("Couldn't create fillet"); return(null); } PolyCurve subResult1 = new PolyCurve { Curves = curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance).ToList() }; PolyCurve subResult2 = new PolyCurve { Curves = curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance).ToList() }; subResult2 = subResult2.Flip(); resultCurves.AddRange(subResult1.Curves); resultCurves.AddRange(subResult2.Curves); } else if (C1SP && !C2SP) { Line tanLine1 = Create.Line(curve1.IEndPoint(), curve1.IEndDir() / tolerance); tanLine1.Infinite = false; PolyCurve pCurve1 = new PolyCurve { Curves = { curve1, tanLine1 } }; Line tanLine2 = Create.Line(curve2.IStartPoint(), curve2.IStartDir().Reverse() / tolerance); tanLine2.Infinite = false; PolyCurve pCurve2 = new PolyCurve { Curves = { tanLine2, curve2 } }; List <Point> curveIntersecions = pCurve1.ICurveIntersections(pCurve2, tolerance); if (curveIntersecions.Count > 0) { intersection = curveIntersecions.ClosestPoint(curve1.IEndPoint()); } else { Reflection.Compute.RecordWarning("Couldn't create fillet"); return(null); } resultCurves.AddRange(curve1.ExtendToPoint(curve1.IStartPoint(), intersection, tangentExtensions, tolerance)); resultCurves.AddRange(curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance)); } else if (!C1SP && C2SP) { Line tanLine1 = Create.Line(curve1.IStartPoint(), curve1.IStartDir().Reverse() / tolerance); tanLine1.Infinite = false; PolyCurve pCurve1 = new PolyCurve { Curves = { tanLine1, curve1 } }; Line tanLine2 = Create.Line(curve2.IEndPoint(), curve2.IEndDir() / tolerance); tanLine2.Infinite = false; PolyCurve pCurve2 = new PolyCurve { Curves = { curve2, tanLine2 } }; List <Point> curveIntersecions = pCurve1.ICurveIntersections(pCurve2, tolerance); if (curveIntersecions.Count > 0) { intersection = curveIntersecions.ClosestPoint(curve1.IStartPoint()); } else { Reflection.Compute.RecordWarning("Couldn't create fillet"); return(null); } PolyCurve subResult1 = new PolyCurve { Curves = curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance).ToList() }; PolyCurve subResult2 = new PolyCurve { Curves = curve2.ExtendToPoint(curve2.IStartPoint(), intersection, tangentExtensions, tolerance).ToList() }; subResult1 = subResult1.Flip(); subResult2 = subResult2.Flip(); resultCurves.AddRange(subResult1.Curves); resultCurves.AddRange(subResult2.Curves); } else { Line tanLine1 = Create.Line(curve1.IStartPoint(), curve1.IStartDir().Reverse() / tolerance); tanLine1.Infinite = false; PolyCurve pCurve1 = new PolyCurve { Curves = { tanLine1, curve1 } }; Line tanLine2 = Create.Line(curve2.IStartPoint(), curve2.IStartDir().Reverse() / tolerance); tanLine2.Infinite = false; PolyCurve pCurve2 = new PolyCurve { Curves = { tanLine2, curve2 } }; List <Point> curveIntersecions = pCurve1.ICurveIntersections(pCurve2, tolerance); if (curveIntersecions.Count > 0) { intersection = curveIntersecions.ClosestPoint(curve1.IStartPoint()); } else { Reflection.Compute.RecordWarning("Couldn't create fillet"); return(null); } PolyCurve subResult1 = new PolyCurve { Curves = curve1.ExtendToPoint(intersection, curve1.IEndPoint(), tangentExtensions, tolerance).ToList() }; PolyCurve subResult2 = new PolyCurve { Curves = curve2.ExtendToPoint(intersection, curve2.IEndPoint(), tangentExtensions, tolerance).ToList() }; subResult1 = subResult1.Flip(); resultCurves.AddRange(subResult1.Curves); resultCurves.AddRange(subResult2.Curves); } } } } for (int i = resultCurves.Count - 1; i >= 0; i--) { if (resultCurves[i] is PolyCurve) { PolyCurve temp = (PolyCurve)resultCurves[i]; resultCurves.RemoveAt(i); resultCurves.InsertRange(i, temp.Curves); } } PolyCurve result = new PolyCurve { Curves = resultCurves }; return(result); }
/***************************************************/ /**** Private methods ****/ /***************************************************/ private bool CreateCollection(IEnumerable <Panel> bhomPanels) { //Code for creating a collection of floors and walls in the software List <Panel> panels = bhomPanels.ToList(); // Register Floor types IFloorType ramFloorType; IStories ramStories; IStory ramStory; //Create wall and floor lists with individual heights List <Panel> wallPanels = new List <Panel>(); List <Panel> floors = new List <Panel>(); List <double> panelHeights = new List <double>(); List <Point> panelPoints = new List <Point>(); // Split walls and floors and get all elevations foreach (Panel panel in panels) { double panelNormZ = panel.Normal().Z; //Split walls and floors if (Math.Abs(panelNormZ) < 0.707) // check normal against 45 degree slope { wallPanels.Add(panel); } else { floors.Add(panel); } } ramStories = m_Model.GetStories(); #region Create Floors // Cycle through floors and create on story foreach (Panel panel in floors) { RAMId RAMId = new RAMId(); string name = panel.Name; PolyCurve outlineExternal = panel.OutlineCurve(); ramStory = panel.GetStory(ramStories); ramFloorType = ramStory.GetFloorType(); try { // Set slab edges on FloorType in RAM for external edges ISlabEdges ramSlabEdges = ramFloorType.GetAllSlabEdges(); ISlabEdges ramOpeningEdges = ramFloorType.GetAllSlabOpenings(); // Get external and internal edges of floor panel List <PolyCurve> panelOutlines = new List <PolyCurve>(); List <PolyCurve> openingOutlines = new List <PolyCurve>(); Vector zDown = BH.Engine.Geometry.Create.Vector(0, 0, -1); // RAM requires edges clockwise, flip if counterclockwise PolyCurve cwOutline = (outlineExternal.IsClockwise(zDown) == false) ? outlineExternal.Flip() : outlineExternal; List <ICurve> edgeCrvs = cwOutline.Curves; foreach (ICurve crv in edgeCrvs) { Point startPt = crv.IStartPoint(); Point endPt = crv.IEndPoint(); ramSlabEdges.Add(startPt.X.ToInch(), startPt.Y.ToInch(), endPt.X.ToInch(), endPt.Y.ToInch(), 0); } List <Opening> panelOpenings = panel.Openings; foreach (Opening opening in panelOpenings) { PolyCurve outlineOpening = opening.OutlineCurve(); openingOutlines.Add(outlineOpening); } foreach (PolyCurve outline in openingOutlines) { // RAM requires edges clockwise, flip if counterclockwise PolyCurve cwOpenOutline = (outline.IsClockwise(zDown) == false) ? outline.Flip() : outline; if (!(outlineExternal.IsContaining(cwOpenOutline, false))) { cwOpenOutline = outlineExternal.BooleanIntersection(cwOpenOutline)[0]; Engine.Base.Compute.RecordWarning("Panel " + name + " opening intersects floor boundary. Boolean intersection was used to get opening extents on panel, confirm opening extents in RAM."); } List <ICurve> openEdgeCrvs = cwOpenOutline.Curves; foreach (ICurve crv in openEdgeCrvs) { Point startPt = crv.IStartPoint(); Point endPt = crv.IEndPoint(); ramOpeningEdges.Add(startPt.X.ToInch(), startPt.Y.ToInch(), endPt.X.ToInch(), endPt.Y.ToInch(), 0); } } // Create Deck List <Point> ctrlPoints = cwOutline.ControlPoints(); if (ctrlPoints.First() != ctrlPoints.Last()) { ctrlPoints.Add(ctrlPoints.Last().DeepClone()); } ISurfaceProperty srfProp = panel.Property; int deckProplUID = GetAdapterId <int>(srfProp); //Add decks, then set deck points per outline IDecks ramDecks = ramFloorType.GetDecks(); IDeck ramDeck = ramDecks.Add(deckProplUID, ctrlPoints.Count); IPoints ramPoints = ramDeck.GetPoints(); // Create list of SCoordinates for floor outlines List <SCoordinate> cornersExt = new List <SCoordinate>(); foreach (Point point in ctrlPoints) { SCoordinate cornerExt = point.ToRAM(); cornersExt.Add(cornerExt); } for (int k = 0; k < cornersExt.Count; k++) { ramPoints.Delete(k); ramPoints.InsertAt(k, cornersExt[k]); } ramDeck.SetPoints(ramPoints); // Add warning to report floors flattened to level as required for RAM if (Math.Abs(panel.Normal().Z) < 1) { Engine.Base.Compute.RecordWarning("Panel " + name + " snapped to level " + ramStory.strLabel + "."); } } catch { CreateElementError("panel", name); } } #endregion #region Create Walls //Cycle through walls; if wall crosses level place at level foreach (Panel wallPanel in wallPanels) { string name = wallPanel.Name; try { double thickness = 0.2; // default thickness if (wallPanel.Property is ConstantThickness) { ConstantThickness prop = (ConstantThickness)wallPanel.Property; thickness = prop.Thickness; } // Find outline of planar panel PolyCurve outline = BH.Engine.Spatial.Query.OutlineCurve(wallPanel); List <Point> wallPts = outline.DiscontinuityPoints(); List <Point> sortedWallPts = wallPts.OrderBy(p => p.X).ToList(); Point leftPt = sortedWallPts.First(); Point rtPt = sortedWallPts.Last(); bool downToRight = leftPt.Y > rtPt.Y; BoundingBox wallBounds = BH.Engine.Geometry.Query.Bounds(outline); Point wallMin = wallBounds.Min; Point wallMax = wallBounds.Max; double tempY = wallMin.Y; wallMin.Y = downToRight ? wallMax.Y : wallMin.Y; wallMax.Y = downToRight ? tempY : wallMax.Y; for (int i = 0; i < ramStories.GetCount(); i++) { ramStory = ramStories.GetAt(i); // If wall crosses level, add wall to ILayoutWalls for that level if (Math.Round(wallMax.Z.ToInch(), 0) >= ramStory.dElevation && Math.Round(wallMin.Z.ToInch(), 0) < ramStory.dElevation) { ramFloorType = ramStory.GetFloorType(); //Get ILayoutWalls of FloorType and add wall ILayoutWalls ramLayoutWalls = ramFloorType.GetLayoutWalls(); ILayoutWall ramLayoutWall = ramLayoutWalls.Add(EMATERIALTYPES.EWallPropConcreteMat, wallMin.X.ToInch(), wallMin.Y.ToInch(), 0, 0, wallMax.X.ToInch(), wallMax.Y.ToInch(), 0, 0, thickness.ToInch()); //Set lateral ramLayoutWall.eFramingType = EFRAMETYPE.MemberIsLateral; IWalls ramWalls = ramLayoutWall.GetAssociatedStoryWalls(); IWall ramWall = ramWalls.GetAt(0); // Find opening location, width, and height from outline and apply foreach (Opening open in wallPanel.Openings) { PolyCurve openOutline = open.OutlineCurve(); BoundingBox openBounds = BH.Engine.Geometry.Query.Bounds(openOutline); Point openMin = openBounds.Min; Point openMax = openBounds.Max; if ((openMin.Z.ToInch() >= ramStory.dElevation - ramStory.dFlrHeight) && (openMin.Z.ToInch() < ramStory.dElevation)) { IFinalWallOpenings ramWallOpenings = ramWall.GetFinalOpenings(); int openOverlapCount = 0; for (int j = 0; i < ramWallOpenings.GetCount(); j++) { IFinalWallOpening testOpen = ramWallOpenings.GetAt(j); IPoints openingPts = testOpen.GetOpeningVertices(); //Re-add first point to close Polygon IPoint firstOPt = openingPts.GetAt(0); SCoordinate firstOCoord = new SCoordinate(); firstOPt.GetCoordinate(ref firstOCoord); openingPts.Add(firstOCoord); Polyline wallOpeningOutline = openingPts.ToPolyline(); List <Point> intPts = wallOpeningOutline.ICurveIntersections(openOutline); if (wallOpeningOutline.IsContaining(openOutline) || openOutline.IsContaining(wallOpeningOutline) || intPts.Count > 0) { openOverlapCount += 1; } } if (openOverlapCount == 0) { //Get opening on wall extents if (!(outline.IsContaining(openOutline, false))) { openOutline = outline.BooleanIntersection(openOutline)[0]; Engine.Base.Compute.RecordWarning("Panel " + name + " opening intersects wall boundary. Boolean intersection was used to get opening extents on panel."); } Point closestOpenPt = BH.Engine.Geometry.Query.ClosestPoint(wallMin, openOutline.ControlPoints()); double distX = Math.Sqrt(Math.Pow(closestOpenPt.X - wallMin.X, 2) + Math.Pow(closestOpenPt.Y - wallMin.Y, 2)); double distZinch = openBounds.Min.Z.ToInch() - (ramStory.dElevation - ramStory.dFlrHeight); double openWidth = Math.Sqrt(Math.Pow(openBounds.Max.X - openBounds.Min.X, 2) + Math.Pow(openBounds.Max.Y - openBounds.Min.Y, 2)); double openHt = openBounds.Max.Z - openBounds.Min.Z; //Add opening to RAM IRawWallOpenings ramRawWallOpenings = ramWall.GetRawOpenings(); ramRawWallOpenings.Add(EDA_MEMBER_LOC.eBottomStart, distX.ToInch(), distZinch, openWidth.ToInch(), openHt.ToInch()); } } } } } } catch { CreateElementError("panel", name); } } #endregion //Save file m_IDBIO.SaveDatabase(); return(true); }