public void ApplyOrthographicCentered() { ViewMatrix = Matrix4.View(Position, LookAtPosition, UpPosition - Position); ProjectionMatrix = Matrix4.OrthographicCentered(ViewPort.Size.Width, ViewPort.Size.Height, Near, Far); TransformMatrix = ViewMatrix.Multiply(ProjectionMatrix); TransformInverseMatrix = TransformMatrix.Invert(); }
public void Apply() { ViewMatrix = Matrix4.View(Position, LookAtPosition, UpPosition - Position); ProjectionMatrix = Matrix4.Perspective(Fov, float.IsNaN(Aspect) ? ViewPort.AspectRatio : Aspect, Near, Far); TransformMatrix = ViewMatrix.Multiply(ProjectionMatrix); TransformInverseMatrix = TransformMatrix.Invert(); }
public static AnalysisGrid AnalysisGrid(this Polyline externalBoundary, List <Polyline> innerBoundaries = null, int id = -1, string name = "", double gridSpacing = 0.2, double edgeOffset = 0.1, double pointOffset = 0.765) { innerBoundaries = innerBoundaries ?? new List <Polyline>(); if (id == -1) { BH.Engine.Reflection.Compute.RecordWarning("ID has not been set to a valid ID, this may cause errors in processing results from this AnalysisGrid if it cannot be uniquely identified later"); } if (name == "") { BH.Engine.Reflection.Compute.RecordWarning("Name has not been set to a valid Name, this may cause confusion in reading results from this AnalysisGrid if it cannot be attributed to the model later"); } //Get the normal from the external boundary Vector surfaceNormal = externalBoundary.Normal().Normalise(); //Offset the external boundary inwards by the edgeOffset amount Polyline offsetCurve = externalBoundary.Offset(-edgeOffset); //Offset the opening curves by the edgeOffset amount List <Polyline> offsetInner = new List <Polyline>(); foreach (Polyline p in innerBoundaries) { offsetInner.Add(p.Offset(edgeOffset)); } //Project all of the geometry to the XY plane Vector zVector = BH.Engine.Geometry.Create.Vector(0, 0, 1); Plane curvePlane = offsetCurve.IFitPlane(); Vector curvePlaneNormal = curvePlane.Normal; List <Point> vertices = offsetCurve.IDiscontinuityPoints(); Point referencePoint = vertices.Min(); Point xyReferencePoint = BH.Engine.Geometry.Create.Point(referencePoint.X, referencePoint.Y, 0); Vector translateVector = xyReferencePoint - referencePoint; Vector rotationVector = curvePlaneNormal.CrossProduct(zVector).Normalise(); double rotationAngle = curvePlaneNormal.Angle(zVector); TransformMatrix transformMatrix = BH.Engine.Geometry.Create.RotationMatrix(vertices.Min(), rotationVector, rotationAngle); Polyline transformedCurve = offsetCurve.Transform(transformMatrix).Translate(translateVector); List <Polyline> transformedHoles = new List <Polyline>(); foreach (Polyline h in offsetInner) { transformedHoles.Add(h.Transform(transformMatrix).Translate(translateVector)); } //Create a grid of points across the flattened curves List <Point> vs = transformedCurve.IDiscontinuityPoints(); List <double> xValues = vs.Select(x => x.X).ToList(); List <double> yValues = vs.Select(x => x.Y).ToList(); double gridSizeX = Math.Round((xValues.Max() - xValues.Min()) / gridSpacing); double gridSizeY = Math.Round((yValues.Max() - yValues.Min()) / gridSpacing); List <Point> pts = new List <Point>(); for (int i = 0; i < gridSizeX; i++) { for (int j = 0; j < gridSizeY; j++) { pts.Add(new Point { X = xValues.Min() + i * gridSpacing + 0.5 * gridSpacing, Y = yValues.Min() + j * gridSpacing + 0.5 * gridSpacing }); } } //Remove points within hole curves List <Point> ptsCleaned = new List <Point>(); foreach (Point pt in pts) { Polyline containedByHole = transformedHoles.Where(x => x.IsContaining(new List <Point> { pt })).FirstOrDefault(); if (containedByHole == null) { //Point is not contained by any opening if (transformedCurve.IsContaining(new List <Point> { pt })) { ptsCleaned.Add(pt); //Point is contained by the external boundary } } } //Retransform the analsyis points back to their original plane List <Point> ptsCleanedRetransformed = new List <Point>(); foreach (Point p in ptsCleaned) { ptsCleanedRetransformed.Add(p.Translate(translateVector.Reverse()).Transform(transformMatrix.Invert()).Translate(surfaceNormal * pointOffset)); } //Create the nodes for the grid List <Node> nodes = new List <Node>(); for (int x = 0; x < ptsCleanedRetransformed.Count; x++) { nodes.Add(new Node { ID = (x + 1), Position = ptsCleanedRetransformed[x] }); } AnalysisGrid grid = new AnalysisGrid(externalBoundary, new ReadOnlyCollection <Polyline>(innerBoundaries), new ReadOnlyCollection <Node>(nodes), id); grid.Name = name; return(grid); }
public static List <Polyline> DelaunayTriangulation(this Polyline outerCurve, List <Polyline> innerCurves = null, double offsetDistance = -0.001, bool conformingDelaunay = true) { if (outerCurve == null) { BH.Engine.Base.Compute.RecordError("Cannot perform Delaunay Triangulation on an outer curve that is set to null."); return(new List <Polyline>()); } // Create a zero length list if no holes input if (innerCurves == null) { innerCurves = new List <Polyline>(); } double area = outerCurve.Area(); for (int x = 0; x < innerCurves.Count; x++) { Polyline pLine = outerCurve.BooleanDifference(new List <Polyline> { innerCurves[x] })[0]; if (pLine.Area() != area) { //The boolean difference returned a different polyline - offset this inner curve innerCurves[x] = innerCurves[x].Offset(offsetDistance); } } // Get the transformation matrix Plane plane = outerCurve.IFitPlane(); Vector normal = plane.Normal; List <Point> vertices = outerCurve.IDiscontinuityPoints(); Point refPoint = vertices.Min(); Point refPointP = BH.Engine.Geometry.Create.Point(refPoint.X, refPoint.Y, 0); Vector zVector = BH.Engine.Geometry.Create.Vector(0, 0, 1); Vector rotationVector = normal.CrossProduct(zVector).Normalise(); double rotationAngle = normal.Angle(zVector); TransformMatrix transformMatrix = BH.Engine.Geometry.Create.RotationMatrix(vertices.Min(), rotationVector, rotationAngle); // Get the translation vector Vector translateVector = refPointP - refPoint; // Transform the original input curve/s Polyline transformedCurve = Modify.Translate(outerCurve.Transform(transformMatrix), translateVector); List <Polyline> transformedHole = new List <Polyline>(); foreach (Polyline h in innerCurves) { if (h.IsCoplanar(outerCurve)) { transformedHole.Add(Modify.Translate(h.Transform(transformMatrix), translateVector)); } } // Convert geometry to Triangle inputs TriangleNet.Geometry.Polygon parentPolygon = new TriangleNet.Geometry.Polygon(); List <TriangleNet.Geometry.Vertex> parentVertices = new List <TriangleNet.Geometry.Vertex>(); foreach (Point point in transformedCurve.IDiscontinuityPoints()) { parentPolygon.Add(new TriangleNet.Geometry.Vertex(point.X, point.Y)); parentVertices.Add(new TriangleNet.Geometry.Vertex(point.X, point.Y)); } TriangleNet.Geometry.Contour parentContour = new TriangleNet.Geometry.Contour(parentVertices); parentPolygon.Add(parentContour); foreach (Polyline h in transformedHole) { List <TriangleNet.Geometry.Vertex> childVertices = new List <TriangleNet.Geometry.Vertex>(); foreach (Point point in h.IDiscontinuityPoints()) { childVertices.Add(new TriangleNet.Geometry.Vertex(point.X, point.Y)); } TriangleNet.Geometry.Contour childContour = new TriangleNet.Geometry.Contour(childVertices); Point childCentroid = h.PointInRegion(); parentPolygon.Add(childContour, new TriangleNet.Geometry.Point(childCentroid.X, childCentroid.Y)); } // Triangulate TriangleNet.Meshing.ConstraintOptions options = new TriangleNet.Meshing.ConstraintOptions() { ConformingDelaunay = conformingDelaunay, }; TriangleNet.Meshing.QualityOptions quality = new TriangleNet.Meshing.QualityOptions() { }; TriangleNet.Mesh mesh = (TriangleNet.Mesh)TriangleNet.Geometry.ExtensionMethods.Triangulate(parentPolygon, options, quality); // Convert triangulations back to BHoM geometry List <Polyline> translatedPolylines = new List <Polyline>(); foreach (var face in mesh.Triangles) { // List points defining the triangle List <Point> pts = new List <Point>(); pts.Add(BH.Engine.Geometry.Create.Point(face.GetVertex(0).X, face.GetVertex(0).Y)); pts.Add(BH.Engine.Geometry.Create.Point(face.GetVertex(1).X, face.GetVertex(1).Y)); pts.Add(BH.Engine.Geometry.Create.Point(face.GetVertex(2).X, face.GetVertex(2).Y)); pts.Add(pts.First()); translatedPolylines.Add(BH.Engine.Geometry.Create.Polyline(pts)); } // Translate back to original plane List <Polyline> meshPolylines = new List <Polyline>(); foreach (Polyline pl in translatedPolylines) { TransformMatrix matrixTransposed = transformMatrix.Invert(); Polyline meshPolyline = pl.Translate(-translateVector).Transform(transformMatrix.Invert()); meshPolylines.Add(meshPolyline); } return(meshPolylines); }
public static Point BottomLeft(this Polyline polyline, List <Panel> panelsAsSpace) { if (polyline == null) { BH.Engine.Reflection.Compute.RecordError("Cannot query the bottom left corner of a null polyline."); return(null); } if (panelsAsSpace == null) { BH.Engine.Reflection.Compute.RecordError("Cannot query the bottom left corner of a polyline without knowing the space it belongs to."); return(null); } Vector normal = polyline.Normal(); if (!polyline.NormalAwayFromSpace(panelsAsSpace)) { normal = polyline.Flip().Normal(); } if (normal == null) { return(null); } Point centre = polyline.Centroid(); if (centre == null) { centre = polyline.ControlPoints.CullDuplicates().Average(); } Line line = new Line { Start = centre, End = centre.Translate(normal), }; List <Point> pnts = polyline.DiscontinuityPoints(); bool wasFlat = false; TransformMatrix transform = null; if (pnts.Min(x => Math.Round(x.Z, 6)) == pnts.Max(x => Math.Round(x.Z, 6))) { //All the points are on the same Z level - we're looking at a floor/roof transform = BH.Engine.Geometry.Create.RotationMatrix(polyline.Centroid(), new Vector { X = 1, Y = 0, Z = 0 }, 1.5708); polyline = polyline.Transform(transform); pnts = polyline.ControlPoints; line.End = line.Start.Translate(polyline.Normal()); wasFlat = true; } Point leftMost = null; foreach (Point p in pnts) { if (IsLeft(line, p) && (leftMost == null || leftMost.Z > p.Z)) { leftMost = p; } } if (wasFlat && leftMost != null) { leftMost = leftMost.Transform(transform.Invert()); } return(leftMost); }
public static Point BottomRight(this Polyline polyline, List <Panel> panelsAsSpace) { Vector normal = polyline.Normal(); if (!polyline.NormalAwayFromSpace(panelsAsSpace)) { normal = polyline.Flip().Normal(); } Point centre = polyline.Centroid(); if (centre == null) { centre = polyline.Centre(); } if (normal == null) { return(null); } Line line = new Line { Start = centre, End = centre.Translate(normal), }; List <Point> pnts = polyline.DiscontinuityPoints(); bool wasFlat = false; TransformMatrix transform = null; if (pnts.Min(x => Math.Round(x.Z, 6)) == pnts.Max(x => Math.Round(x.Z, 6))) { //All the points are on the same Z level - we're looking at a floor/roof transform = BH.Engine.Geometry.Create.RotationMatrix(polyline.Centroid(), new Vector { X = 1, Y = 0, Z = 0 }, 1.5708); polyline = polyline.Transform(transform); pnts = polyline.ControlPoints; line.End = line.Start.Translate(polyline.Normal()); wasFlat = true; } Point rightMost = null; foreach (Point p in pnts) { if (!IsLeft(line, p) && (rightMost == null || rightMost.Z > p.Z)) { rightMost = p; } } if (wasFlat && rightMost != null) { rightMost = rightMost.Transform(transform.Invert()); } return(rightMost); }