public static bool NormalTowardsSpace(this BHG.Polyline pline, BHE.Space space) { BHG.Point centrePt = pline.Centre(); List <BHG.Point> pts = BH.Engine.Geometry.Query.DiscontinuityPoints(pline); BHG.Plane plane = BH.Engine.Geometry.Create.Plane(pts[0], pts[1], pts[2]); //The polyline can be locally concave. Check if the polyline is clockwise. if (!BH.Engine.Geometry.Query.IsClockwise(pline, plane.Normal)) { plane.Normal = -plane.Normal; } //Move centrepoint along the normal. If inside - flip the panel if (IsContaining(space, centrePt.Translate(plane.Normal))) { return(true); } else { return(false); } /***************************************************/ }
/***************************************************/ private static bool TryAddSurface(this BRepBuilder brep, PlanarSurface ps) { try { BH.oM.Geometry.Plane p = ps.ExternalBoundary.IFitPlane(); Autodesk.Revit.DB.Plane rp = p.ToRevit(); BRepBuilderSurfaceGeometry bbsg = BRepBuilderSurfaceGeometry.Create(rp, null); BRepBuilderGeometryId face = brep.AddFace(bbsg, false); brep.AddLoop(face, rp.Normal, ps.ExternalBoundary, true); foreach (ICurve c in ps.InternalBoundaries) { brep.AddLoop(face, rp.Normal, c, false); } brep.FinishFace(face); } catch { BH.Engine.Reflection.Compute.RecordError("An attempt to create a planar surface failed."); return(false); } return(true); }
/***************************************************/ public static void RenderWires(BHG.Plane plane, Rhino.Display.DisplayPipeline pipeline, Color bhColour) { pipeline.DrawConstructionPlane(new Rhino.DocObjects.ConstructionPlane() { Plane = (plane.ToRhino()), ThickLineColor = bhColour, ThinLineColor = Color.Black, GridLineCount = 10 }); }
/***************************************************/ public static RHG.Plane ToRhino(this BHG.Plane plane) { if (plane == null) { return(default(RHG.Plane)); } return(new RHG.Plane(plane.Origin.ToRhino(), plane.Normal.ToRhino())); }
/***************************************************/ /**** Public Methods - Vectors ****/ /***************************************************/ public static bool IsEqual(this BHG.Plane bhPlane, RHG.Plane rhPlane, double tolerance = BHG.Tolerance.Distance) { if (bhPlane == null & rhPlane == default(RHG.Plane)) { return(true); } return(bhPlane.Origin.IsEqual(rhPlane.Origin, tolerance) && bhPlane.Normal.IsEqual(rhPlane.Normal, tolerance)); }
/***************************************************/ public static bool NormalAwayFromSpace(this BHG.Polyline pline, List <BHE.BuildingElement> elementsAsSpace) { List <BHG.Point> centrePtList = new List <BHG.Point>(); BHG.Point centrePt = pline.Centre(); centrePtList.Add(centrePt); if (!pline.IsClosed()) { return(false); //Prevent failures of the clockwise check } List <BHG.Point> pts = BH.Engine.Geometry.Query.DiscontinuityPoints(pline); if (pts.Count < 3) { return(false); //Protection in case there aren't enough points to make a plane } BHG.Plane plane = BH.Engine.Geometry.Create.Plane(pts[0], pts[1], pts[2]); //The polyline can be locally concave. Check if the polyline is clockwise. if (!BH.Engine.Geometry.Query.IsClockwise(pline, plane.Normal)) { plane.Normal = -plane.Normal; } if (!BH.Engine.Geometry.Query.IsContaining(pline, centrePtList, false)) { BHG.Point pointOnLine = BH.Engine.Geometry.Query.ClosestPoint(pline, centrePt); BHG.Vector vector = new BHG.Vector(); if (BH.Engine.Geometry.Query.Distance(pointOnLine, centrePt) > BH.oM.Geometry.Tolerance.MicroDistance) { vector = pointOnLine - centrePt; } else { BHG.Line line = BH.Engine.Geometry.Query.GetLineSegment(pline, pointOnLine); vector = ((line.Start - line.End).Normalise()).CrossProduct(plane.Normal); } centrePt = BH.Engine.Geometry.Modify.Translate(pointOnLine, BH.Engine.Geometry.Modify.Normalise(vector) * 0.001); } //Move centrepoint along the normal. if (BH.Engine.Environment.Query.IsContaining(elementsAsSpace, centrePt.Translate(plane.Normal * 0.01))) { return(false); } else { return(true); } }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static double Orientation(IBuildingObject buildingPanel) { Panel panel = buildingPanel as Panel; BHG.Polyline pLine = new BHG.Polyline { ControlPoints = panel.PanelCurve.IControlPoints() }; List <BHG.Point> pts = pLine.DiscontinuityPoints(); BHG.Plane plane = BH.Engine.Geometry.Create.Plane(pts[0], pts[1], pts[2]); //Some protection on this needed maybe? BHG.Vector xyNormal = BH.Engine.Geometry.Create.Vector(0, 1, 0); return(BH.Engine.Geometry.Query.Angle(plane.Normal, xyNormal) * (180 / Math.PI)); }
/***************************************************/ public static double Azimuth(this BHG.Polyline pline, BHG.Vector refVector) { double azimuth; List <BHG.Point> pts = BH.Engine.Geometry.Query.DiscontinuityPoints(pline); if (pts.Count < 3 || !BH.Engine.Geometry.Query.IsClosed(pline)) { return(-1); //Protection in case there aren't enough points to make a plane } BHG.Plane plane = BH.Engine.Geometry.Create.Plane(pts[0], pts[1], pts[2]); //The polyline can be locally concave. Check if the polyline is clockwise. if (!BH.Engine.Geometry.Query.IsClockwise(pline, plane.Normal)) { plane.Normal = -plane.Normal; } if (Geometry.Modify.Normalise(plane.Normal).Z == 1) { azimuth = 0; } else if (Geometry.Modify.Normalise(plane.Normal).Z == -1) { azimuth = 180; } else { BHG.Vector v1 = Geometry.Modify.Project(plane.Normal, BHG.Plane.XY); BHG.Vector v2 = (Geometry.Modify.Project(refVector, BHG.Plane.XY)); azimuth = (BH.Engine.Geometry.Query.SignedAngle(v1, v2, BHG.Vector.ZAxis) * (180 / Math.PI)); if (azimuth < 0) { azimuth = 360 + azimuth; } } return(azimuth); }
/***************************************************/ public static double Tilt(this BHG.Polyline pline) { double tilt; List <BHG.Point> pts = BH.Engine.Geometry.Query.DiscontinuityPoints(pline); if (pts.Count < 3 || !BH.Engine.Geometry.Query.IsClosed(pline)) { return(-1); //Error protection on pts having less than 3 elements to create a plane or pLine not being closed } BHG.Plane plane = BH.Engine.Geometry.Create.Plane(pts[0], pts[1], pts[2]); //The polyline can be locally concave. Check if the polyline is clockwise. if (!BH.Engine.Geometry.Query.IsClockwise(pline, plane.Normal)) { plane.Normal = -plane.Normal; } tilt = BH.Engine.Geometry.Query.Angle(plane.Normal, BHG.Plane.XY.Normal) * (180 / Math.PI); return(tilt); }
/***************************************************/ /**** Public Methods ****/ /***************************************************/ public static Element ToCurveElement(this ModelInstance modelInstance, Document document, RevitSettings settings = null, Dictionary <Guid, List <int> > refObjects = null) { CurveElement curveElement = refObjects.GetValue <CurveElement>(document, modelInstance.BHoM_Guid); if (curveElement != null) { return(curveElement); } settings = settings.DefaultIfNull(); ICurve curve = modelInstance.Location as ICurve; if (curve == null) { return(null); } if (!curve.IIsPlanar(settings.DistanceTolerance)) { modelInstance.NonPlanarCurveError(); return(null); } Curve revitCurve = curve.IToRevit(); if (revitCurve == null) { return(null); } if ((revitCurve is NurbSpline || revitCurve is HermiteSpline) && curve.IIsClosed(settings.DistanceTolerance)) { modelInstance.ClosedNurbsCurveError(); return(null); } Autodesk.Revit.DB.Plane revitPlane; BH.oM.Geometry.Plane plane = curve.IFitPlane(); if (plane == null) { revitPlane = revitCurve.ArbitraryPlane(); } else { revitPlane = plane.ToRevit(); } SketchPlane sketchPlane = SketchPlane.Create(document, revitPlane); curveElement = document.Create.NewModelCurve(revitCurve, sketchPlane); if (modelInstance.Properties != null) { string name = modelInstance.Properties.Name; if (!string.IsNullOrEmpty(name)) { Element element = new FilteredElementCollector(document).OfClass(typeof(GraphicsStyle)).ToList().Find(x => x.Name == name); if (element != null) { curveElement.LineStyle = element; } } } refObjects.AddOrReplace(modelInstance, curveElement); return(curveElement); }
/***************************************************/ public static void RenderMeshes(BHG.Plane plane, Rhino.Display.DisplayPipeline pipeline, DisplayMaterial material) { return; }
public static List <Slice> CreateSlices(Group <Curve> edges, Vector direction, double increment = 0.001) { List <Slice> slices = new List <Slice>(); List <double> cutAt = new List <double>(); List <double> sliceSegments = new List <double>(); Plane p = new BH.oM.Geometry.Plane(Point.Origin, direction); for (int i = 0; i < edges.Count; i++) { for (int j = 0; j < edges[i].PointCount; j++) { cutAt.Add(ArrayUtils.DotProduct(edges[i].ControlPoint(j), p.Normal)); } } cutAt.Sort(); cutAt = cutAt.Distinct <double>().ToList(); double currentValue = ArrayUtils.DotProduct(edges.Bounds().Min, p.Normal); double max = ArrayUtils.DotProduct(edges.Bounds().Max, p.Normal); int index = 0; while (currentValue < max) { if (cutAt.Count > index && currentValue > cutAt[index]) { sliceSegments.Add(cutAt[index]); index++; } else { sliceSegments.Add(currentValue); currentValue += increment; } } sliceSegments.Add(max); for (int i = 0; i < sliceSegments.Count - 1; i++) { if (sliceSegments[i] == sliceSegments[i + 1]) { continue; } currentValue = (sliceSegments[i] + sliceSegments[i + 1]) / 2; //for (int edgeIndex = 0; edgeIndex < m_Edges.Count; edgeIndex++) //{ // if (edgeIndex == 3) // { // } // y.AddRange(Intersect.PlaneCurve(new Plane(new Point(p.Normal * currentValue), p.Normal), m_Edges[edgeIndex], 0.00001)); //} //List<double> isolatedCoords = new List<double>(); //for (int point = 0; point < y.Count; point++) //{ // if (p.Normal.X > 0) // { // isolatedCoords.Add(y[point].Y); // } // else // { // isolatedCoords.Add(y[point].X); // } //} //isolatedCoords.Sort(); //if (isolatedCoords.Count % 2 != 0) //{ // for (int k = 0; k < isolatedCoords.Count - 1; k++) // { // if (isolatedCoords[k] == isolatedCoords[k + 1]) // { // isolatedCoords.RemoveAt(k + 1); // } // } //} //for (int j = 0; j < isolatedCoords.Count - 1; j += 2) //{ // length = length + isolatedCoords[j + 1] - isolatedCoords[j]; //} slices.Add(GetSliceAt(edges, currentValue, -sliceSegments[i] + sliceSegments[i + 1], p)); //new Slice(-sliceSegments[i] + sliceSegments[i + 1], length, currentValue, isolatedCoords.ToArray())); } return(slices); }
/***************************************************/ /**** Public methods ****/ /***************************************************/ public static Floor ToRevitFloor(this oM.Physical.Elements.Floor floor, Document document, RevitSettings settings = null, Dictionary <Guid, List <int> > refObjects = null) { if (floor == null || floor.Construction == null || document == null) { return(null); } Floor revitFloor = refObjects.GetValue <Floor>(document, floor.BHoM_Guid); if (revitFloor != null) { return(revitFloor); } PlanarSurface planarSurface = floor.Location as PlanarSurface; if (planarSurface == null) { return(null); } settings = settings.DefaultIfNull(); FloorType floorType = floor.Construction?.ToRevitElementType(document, new List <BuiltInCategory> { BuiltInCategory.OST_Floors }, settings, refObjects) as FloorType; if (floorType == null) { floorType = floor.ElementType(document, settings); } if (floorType == null) { Compute.ElementTypeNotFoundWarning(floor); return(null); } double bottomElevation = floor.Location.IBounds().Min.Z; Level level = document.LevelBelow(bottomElevation.FromSI(UnitType.UT_Length), settings); oM.Geometry.Plane sketchPlane = new oM.Geometry.Plane { Origin = new BH.oM.Geometry.Point { Z = bottomElevation }, Normal = Vector.ZAxis }; ICurve curve = planarSurface.ExternalBoundary.IProject(sketchPlane); CurveArray curveArray = Create.CurveArray(curve.IToRevitCurves()); BH.oM.Geometry.Plane slabPlane = planarSurface.FitPlane(); if (1 - Math.Abs(Vector.ZAxis.DotProduct(slabPlane.Normal)) <= settings.AngleTolerance) { revitFloor = document.Create.NewFloor(curveArray, floorType, level, true); } else { Vector normal = slabPlane.Normal; if (normal.Z < 0) { normal = -slabPlane.Normal; } double angle = normal.Angle(Vector.ZAxis); double tan = Math.Tan(angle); XYZ dir = normal.Project(oM.Geometry.Plane.XY).ToRevit().Normalize(); BH.oM.Geometry.Line ln = slabPlane.PlaneIntersection(sketchPlane); XYZ start = ln.ClosestPoint(curveArray.get_Item(0).GetEndPoint(0).PointFromRevit(), true).ToRevit(); Autodesk.Revit.DB.Line line = Autodesk.Revit.DB.Line.CreateBound(start, start + dir); revitFloor = document.Create.NewSlab(curveArray, level, line, -tan, true); revitFloor.SetParameter(BuiltInParameter.ELEM_TYPE_PARAM, floorType.Id); } revitFloor.CheckIfNullPush(floor); if (revitFloor == null) { return(null); } document.Regenerate(); if (planarSurface.InternalBoundaries != null) { foreach (ICurve hole in planarSurface.InternalBoundaries) { document.Create.NewOpening(revitFloor, Create.CurveArray(hole.IProject(slabPlane).IToRevitCurves()), true); } } foreach (BH.oM.Physical.Elements.IOpening opening in floor.Openings) { PlanarSurface openingLocation = opening.Location as PlanarSurface; if (openingLocation == null) { BH.Engine.Reflection.Compute.RecordWarning(String.Format("Conversion of a floor opening to Revit failed because its location is not a planar surface. Floor BHoM_Guid: {0}, Opening BHoM_Guid: {1}", floor.BHoM_Guid, opening.BHoM_Guid)); continue; } document.Create.NewOpening(revitFloor, Create.CurveArray(openingLocation.ExternalBoundary.IToRevitCurves()), true); if (!(opening is BH.oM.Physical.Elements.Void)) { BH.Engine.Reflection.Compute.RecordWarning(String.Format("Revit allows only void openings in floors, therefore the BHoM opening of type {0} has been converted to a void opening. Floor BHoM_Guid: {1}, Opening BHoM_Guid: {2}", opening.GetType().Name, floor.BHoM_Guid, opening.BHoM_Guid)); } } double offset = revitFloor.LookupParameterDouble(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM); // Copy parameters from BHoM object to Revit element revitFloor.CopyParameters(floor, settings); // Update the offset in case the level had been overwritten. if (revitFloor.LevelId.IntegerValue != level.Id.IntegerValue) { Level newLevel = document.GetElement(revitFloor.LevelId) as Level; offset += (level.ProjectElevation - newLevel.ProjectElevation).ToSI(UnitType.UT_Length); } revitFloor.SetParameter(BuiltInParameter.FLOOR_HEIGHTABOVELEVEL_PARAM, offset); refObjects.AddOrReplace(floor, revitFloor); return(revitFloor); }