public static Polyline Rationalise(this Circle circle, RenderMeshOptions renderMeshOptions = null, int minSubdivisions = 3) { renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); Polyline polyline = new Polyline(); List <Point> controlPoints = new List <Point> { circle.IStartPoint() }; // Subdivide the circle. // Empyrical formula to extract a reasonable amount of segments int numSubdvision = (int)(Math.Ceiling(circle.Radius * 10) * renderMeshOptions.Element1DRefinement); // Scale the number of subdivisions based on the Options numSubdvision = (int)Math.Ceiling(numSubdvision * renderMeshOptions.Element1DRefinement); // Check the number of subdivisions is over the minimum acceptable numSubdvision = numSubdvision < minSubdivisions ? minSubdivisions : numSubdvision; if (renderMeshOptions.RepresentationOptions.Detailed1DElements) { numSubdvision = (int)(Math.Ceiling(numSubdvision * 2f)); } List <double> pointParams = Enumerable.Range(0, numSubdvision).Select(i => (double)((double)i / (double)numSubdvision)).ToList(); pointParams.Add(1); controlPoints.AddRange(pointParams.Select(par => circle.IPointAtParameter(par))); polyline.ControlPoints = controlPoints; return(polyline); }
public static BH.oM.Graphics.RenderMesh RenderMesh(this Cone cone, RenderMeshOptions renderMeshOptions = null) { if (cone == null) { BH.Engine.Base.Compute.RecordError("Cannot compute the mesh of a null cone."); return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); int coneFaces = 4; // by default this creates a pyramid List <double> pointParams = new List <double>(); if (coneFaces == 4) { pointParams = new List <double>() { 0.125, 0.375, 0.625, 0.875, 0.125 } } ; // for 4 corners, make sure the pyramid is oriented like global axes else { pointParams = Enumerable.Range(0, coneFaces + 1).Select(i => (double)((double)i / (double)coneFaces)).ToList(); } Circle baseCircle = BH.Engine.Geometry.Create.Circle(cone.Centre, cone.Axis, cone.Radius); List <Point> pointsOnBase = pointParams.Select(par => baseCircle.IPointAtParameter(par)).ToList(); Vector coneHeightVector = Compute.Scale(cone.Axis, cone.Height); Point topPoint = new Point() { X = cone.Centre.X + BHEG.Modify.Project(coneHeightVector, BHOG.Plane.XY).X, Y = cone.Centre.Y + BHEG.Modify.Project(coneHeightVector, BHOG.Plane.XY).Y,// Math.Sin(BHEG.Query.Angle(BHEG.Modify.Project(cone.Axis, BHOG.Plane.XY), BHOG.Vector.XAxis)), Z = cone.Centre.Z + coneHeightVector.Z }; List <Face> faces = new List <Face>(); List <Point> vertices = new List <Point>(); vertices.AddRange(pointsOnBase); vertices.Add(topPoint); for (int i = 0; i < pointsOnBase.Count - 1; i++) { faces.Add(new Face() { A = i, B = i + 1, C = vertices.Count - 1 }); } return(new RenderMesh() { Vertices = vertices.Select(pt => (RenderPoint)pt).ToList(), Faces = faces }); }
public static BH.oM.Graphics.RenderMesh RenderMesh(this Cuboid cuboid, RenderMeshOptions renderMeshOptions = null) { if (cuboid == null) { BH.Engine.Base.Compute.RecordError("Cannot compute the mesh of a null cuboid."); return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); return(BoxRenderMesh(cuboid.CoordinateSystem.Origin, cuboid.Length, cuboid.Depth, cuboid.Height, renderMeshOptions)); }
public static BH.oM.Graphics.RenderMesh RenderMesh(this ICurve curve, RenderMeshOptions renderMeshOptions = null) { renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); Polyline polyline = curve.IRationalise(renderMeshOptions); if (polyline != null) { return(polyline.GeometricalRepresentation(renderMeshOptions.RepresentationOptions).IRenderMesh(renderMeshOptions)); } return(null); }
public static Polyline Rationalise(this Arc arc, RenderMeshOptions renderMeshOptions = null, int minSubdivisions = 3) { renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); Polyline polyline = new Polyline(); List <Point> controlPoints = new List <Point> { arc.IStartPoint() }; double arcAngle = Math.Round(Math.Abs(Math.Abs(arc.StartAngle - arc.EndAngle)), 4); double minRadiusForSubdivision = 0.02; double minAngleForSubdivision = 0.1; if (renderMeshOptions.RepresentationOptions.Detailed1DElements) { minRadiusForSubdivision = minRadiusForSubdivision / renderMeshOptions.Element1DRefinement; minAngleForSubdivision = minAngleForSubdivision / renderMeshOptions.Element1DRefinement; } double length = arc.Length(); if (arc.Radius < minRadiusForSubdivision || arcAngle < minAngleForSubdivision) // a very small arc should not be subdivided. { controlPoints.Add(arc.IEndPoint()); } else { // If not, subdivide the arc. int numSubdvision = (int)Math.Abs(Math.Ceiling(1.5708 / (arcAngle) * renderMeshOptions.Element1DRefinement * length / 2) - 1); // Scale the number of subdivisions based on the Options numSubdvision = (int)Math.Ceiling(numSubdvision * renderMeshOptions.Element1DRefinement); // Check the number of subdivisions is over the minimum acceptable numSubdvision = numSubdvision < minSubdivisions ? minSubdivisions : numSubdvision; List <double> pointParams = Enumerable.Range(0, numSubdvision).Select(i => (double)((double)i / (double)numSubdvision)).ToList(); controlPoints.AddRange(pointParams.Select(par => arc.IPointAtParameter(par))); controlPoints.Add(arc.IEndPoint()); } polyline.ControlPoints = controlPoints; return(polyline); }
public static BH.oM.Graphics.RenderMesh IRenderMesh(this IObject obj, RenderMeshOptions renderMeshOptions = null) { if (obj == null) { return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); RenderMesh renderMesh = null; // See if there is a custom BHoM mesh representation for this BHoMObject, before attempting the RenderMesh computation. if (obj is IBHoMObject) { if (Query.TryGetRendermesh(obj as IBHoMObject, out renderMesh)) { return(renderMesh); } } if (obj is BH.oM.Graphics.RenderMesh) { return(obj as BH.oM.Graphics.RenderMesh); } BH.oM.Geometry.Mesh mesh = obj as BH.oM.Geometry.Mesh; if (mesh != null) { return(mesh.ToRenderMesh()); } // If obj is of type IGeometry, we still need to compute its geometrical representation. // E.g. A BH.oM.Geometry.Point can only be represented with a Sphere, a Pixel, a Voxel, etc. IGeometry geomRepr = IGeometricalRepresentation(obj, renderMeshOptions.RepresentationOptions); if (geomRepr != null) { renderMesh = RenderMesh(geomRepr as dynamic, renderMeshOptions); } if (renderMesh == null) { throw new Exception($"Could not compute the {nameof(BH.oM.Graphics.RenderMesh)} of {obj.GetType().Name}."); } return(renderMesh); }
public static Polyline IRationalise(this ICurve curve, RenderMeshOptions renderMeshOptions = null) { if (curve is Polyline) // no need to rationalise { return(curve as Polyline); } if (curve is Line) // no need to rationalise { return new Polyline() { ControlPoints = (curve as Line).ControlPoints() } } ; return(Rationalise(curve as dynamic, renderMeshOptions)); }
public static Polyline Rationalise(this PolyCurve curve, RenderMeshOptions renderMeshOptions = null, int minSubdivisions = 3) { if (curve == null) { BH.Engine.Base.Compute.RecordError("Cannot rationalise a null polycurve."); return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); if (curve.Curves.Count == 0) { return(new Polyline()); } Polyline polyline = new Polyline(); polyline.ControlPoints.Add(curve.SubParts()[0].IStartPoint()); foreach (ICurve c in curve.SubParts()) { Line line = c as Line; if (line != null) { polyline.ControlPoints.Add(line.End); continue; } Polyline rationalised = Rationalise(c as dynamic, renderMeshOptions, minSubdivisions); List <Point> points = rationalised.ControlPoints.Skip(1).ToList(); polyline.ControlPoints.AddRange(points); } if (polyline == null || polyline.ControlPoints.Count < 2) { BH.Engine.Base.Compute.RecordError("Rationalisation of curves currently only supports Arcs."); } return(polyline); }
/***************************************************/ /**** Public Methods - Graphics ****/ /***************************************************/ public static BH.oM.Graphics.RenderMesh RenderMesh(this BoundingBox bbox, RenderMeshOptions renderMeshOptions = null) { if (bbox == null) { BH.Engine.Base.Compute.RecordError("Cannot compute the mesh of a null bounding box."); return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); double length = bbox.Max.X - bbox.Min.X; double depth = bbox.Max.Y - bbox.Min.Y; double height = bbox.Max.Z - bbox.Min.Z; Point centrePoint = new Point() { X = bbox.Min.X + length / 2, Y = bbox.Min.Y + depth / 2, Z = bbox.Min.Z + height / 2 }; return(BoxRenderMesh(centrePoint, length, depth, height)); }
public static IBHoMObject ISetRendermesh(this IBHoMObject bHoMObject, object meshRepresentation = null, RenderMeshOptions renderMeshOptions = null) { if (bHoMObject == null) { return(null); } if (meshRepresentation == null) { // Try computing a RenderMesh from the specified representation Geometry RenderMesh rm = Compute.IRenderMesh(bHoMObject, renderMeshOptions); if (rm == null) { BH.Engine.Base.Compute.RecordError($"The input {nameof(meshRepresentation)} was null. The method attempted to compute a RenderMesh for the object, but this failed."); return(null); } return(SetRendermesh(bHoMObject, rm)); } return(SetRendermesh(bHoMObject, meshRepresentation as dynamic)); }
public static BH.oM.Graphics.RenderMesh RenderMesh(this Pipe pipe, RenderMeshOptions renderMeshOptions = null) { if (pipe == null) { BH.Engine.Base.Compute.RecordError("Cannot compute the mesh of a null pipe."); return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); double radius = pipe.Radius; bool capped = renderMeshOptions.RepresentationOptions.Cap1DElements; Line centreLine = pipe.Centreline as Line; Polyline centrePolyline = pipe.Centreline as Polyline; if (centreLine != null) { int pipeFaces = (int)Math.Ceiling(3 * renderMeshOptions.Element1DRefinement); List <double> pointParams = Enumerable.Range(0, pipeFaces + 1).Select(i => (double)((double)i / (double)pipeFaces)).ToList(); Circle c = BH.Engine.Geometry.Create.Circle(centreLine.Start, centreLine.Direction(), radius * renderMeshOptions.RepresentationOptions.Element1DScale); var gna = BH.Engine.Geometry.Create.Polyline(pointParams.Select(par => c.IPointAtParameter(par))); Polyline polyline = Rationalise(c, renderMeshOptions); Vector lengthVector = new Vector() { X = centreLine.End.X - centreLine.Start.X, Y = centreLine.End.Y - centreLine.Start.Y, Z = centreLine.End.Z - centreLine.Start.Z }; Extrusion extr = BH.Engine.Geometry.Create.Extrusion(polyline, lengthVector); extr.Capped = capped; return(RenderMesh(extr, renderMeshOptions)); } if (centrePolyline == null) { centrePolyline = pipe.Centreline.IRationalise(renderMeshOptions); // Try rationalising the Curve } if (centrePolyline != null) { RenderMesh unifiedMesh = new RenderMesh(); List <RenderMesh> allMeshes = new List <RenderMesh>(); for (int i = 0; i < centrePolyline.ControlPoints.Count - 1; i++) { Line line = BH.Engine.Geometry.Create.Line(centrePolyline.ControlPoints[i], centrePolyline.ControlPoints[i + 1]); Pipe subPipe = BH.Engine.Geometry.Create.Pipe(line, radius, capped); RenderMesh m = RenderMesh(subPipe, renderMeshOptions); allMeshes.Add(m); // Join the meshes m.Faces.ForEach(f => unifiedMesh.Faces.Add(new Face() { A = f.A + unifiedMesh.Faces.Count, B = f.B + unifiedMesh.Faces.Count, C = f.C + unifiedMesh.Faces.Count, D = f.D + unifiedMesh.Faces.Count })); unifiedMesh.Vertices.AddRange(m.Vertices); } return(allMeshes.JoinRenderMeshes()); } BH.Engine.Base.Compute.RecordError("RenderMesh for Pipe currently only works with pipes made of linear segments (not curved ICurves)."); return(null); }
/***************************************************/ /**** Private methods ****/ /***************************************************/ private static string WriteBIMFile(List <IObject> objectsToWrite, string directory = null, string fileName = null, RenderMeshOptions renderMeshOptions = null) { // --------------------------------------------- // // Set-up // // --------------------------------------------- // directory = directory ?? Path.Combine("C:\\temp", "BIMFileFormat"); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } fileName = fileName ?? Guid.NewGuid().ToString(); string bimFilePath = Path.Combine(directory, fileName + ".bim"); renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); // --------------------------------------------- // // Compute representation // // --------------------------------------------- // List <Mesh> representationMeshes = new List <Mesh>(); List <Tuple <IObject, Mesh> > objsAndRepresentations = new List <Tuple <IObject, Mesh> >(); IBHoMObject bHoMObject = null; for (int i = 0; i < objectsToWrite.Count; i++) { IObject obj = objectsToWrite[i]; Mesh meshRepresentation = null; // See if there is a custom BHoM mesh representation for that BHoMObject. bHoMObject = obj as IBHoMObject; RenderMesh renderMesh = null; if (bHoMObject != null) { bHoMObject.TryGetRendermesh(out renderMesh); } if (renderMesh == null && meshRepresentation == null) { renderMesh = BH.Engine.Representation.Compute.IRenderMesh(obj, renderMeshOptions); } if (renderMesh != null) //convert to Mesh { meshRepresentation = new Mesh() { Faces = renderMesh.Faces, Vertices = renderMesh.Vertices.Select(v => new oM.Geometry.Point() { X = v.Point.X, Y = v.Point.Y, Z = v.Point.Z }).ToList() } } ; representationMeshes.Add(meshRepresentation); if (bHoMObject != null) { // Add/update the RenderMesh in the BHoMObject bHoMObject.ISetRendermesh(meshRepresentation); obj = bHoMObject; } objsAndRepresentations.Add(new Tuple <IObject, Mesh>(obj, meshRepresentation)); } // --------------------------------------------- // // File preparation // // --------------------------------------------- // BIMDataExporter exporter = new BIMDataExporter(); // Prepare default material TDR_Material defaultMat = new TDR_Material() { MaterialArray = new List <float> { 1f, 1f, 1f, 1f } }; int defaultMatIdx = exporter.AddMaterial(defaultMat.MaterialArray); // Prepare transformation matrix List <float> transfMatrix = new List <float> { 1, 0, 0, 2, 0, 1, 0, 2, 0, 0, 1, 2, 0, 0, 0, 1 }; // Prepare root node int rootNodeIdx = exporter.AddNode("root", -1, null); // Process the meshes for (int i = 0; i < objsAndRepresentations.Count; i++) { BH.oM.Geometry.Mesh m = representationMeshes[i]; Tuple <IObject, BH.oM.Geometry.Mesh> objAndRepr = objsAndRepresentations[i]; // Check if a colour has been specified in the BHoMObject's Fragment bHoMObject = objAndRepr.Item1 as IBHoMObject; int customMatIdx = defaultMatIdx; if (bHoMObject != null) { Color?colour = bHoMObject.FindFragment <ColourFragment>()?.Colour; if (colour != null) { Color col = (Color)colour; float r = (float)col.R / 255; float g = (float)col.G / 255; float b = (float)col.B / 255; float a = (float)col.A / 255; TDR_Material customMat = new TDR_Material() { MaterialArray = new List <float> { r, g, b, a } }; customMatIdx = exporter.AddMaterial(customMat.MaterialArray); } } // Convert object representation mesh to a Geometry geometry = BH.Adapter.TDrepo.Convert.MeshToGeometry(objAndRepr.Item2, customMatIdx); // Add metadata Dictionary <string, RepoVariant> metadata = new Dictionary <string, RepoVariant>(); // Serialize the object string serialisedBHoMData = BH.Engine.Serialiser.Convert.ToJson(objAndRepr.Item1); // Flatten the JSON in a Dictionary. Nested properties names are concatenated with fullstops. Dictionary <string, object> flattenedObj = BH.Engine.Adapters.TDRepo.Compute.FlattenJsonToDictionary(serialisedBHoMData); // For each entry in the flattened object, add a metadata with the value. flattenedObj.ToList().ForEach( kv => { if (kv.Value is int) { metadata.Add(kv.Key, RepoVariant.Int((int)kv.Value)); } else if (kv.Value is double) { metadata.Add(kv.Key, RepoVariant.Double((double)kv.Value)); } else if (kv.Value is bool) { metadata.Add(kv.Key, RepoVariant.Boolean((bool)kv.Value)); } else { metadata.Add(kv.Key, RepoVariant.String(kv.Value?.ToString())); } } ); metadata.Add("ZippedBHoM", RepoVariant.String(BH.Engine.Serialiser.Convert.ToZip(serialisedBHoMData))); //metadata.Add("Area", RepoVariant.Int(1)); //metadata.Add("Boolean Test", RepoVariant.Boolean(true)); //metadata.Add("Double", RepoVariant.Double(1.3242524)); // Add node to exporter. exporter.AddNode("mesh" + i, rootNodeIdx, transfMatrix, geometry, metadata); } exporter.ExportToFile(bimFilePath); return(bimFilePath); }
// Fallback private static Polyline Rationalise(this ICurve curve, RenderMeshOptions renderMeshOptions = null) { BH.Engine.Base.Compute.RecordError($"Could not find a method to rationalise the curve {curve.GetType().Name}. Currently support only Arc and Circle."); return(null); }
/***************************************************/ /**** Public Methods - Graphics ****/ /***************************************************/ public static BH.oM.Graphics.RenderMesh RenderMesh(this CompositeGeometry compositeGeometry, RenderMeshOptions renderMeshOptions = null) { if (compositeGeometry == null) { BH.Engine.Base.Compute.RecordError("Cannot compute the mesh of a null composite geometry object."); return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); List <RenderMesh> renderMeshes = new List <RenderMesh>(); for (int i = 0; i < compositeGeometry.Elements.Count; i++) { renderMeshes.Add(IRenderMesh(compositeGeometry.Elements[i])); } return(BH.Engine.Representation.Compute.JoinRenderMeshes(renderMeshes)); }
private static BH.oM.Graphics.RenderMesh BoxRenderMesh(Point centrePoint, double length, double depth, double height, RenderMeshOptions renderMeshOptions = null) { renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); List <RenderPoint> vertices = new List <RenderPoint>(); // Top face (normal to global z, +) //0 vertices.Add((RenderPoint) new Point() { X = centrePoint.X + (length / 2.0), Y = centrePoint.Y + (depth / 2.0), Z = centrePoint.Z + (height / 2.0) }); //1 vertices.Add((RenderPoint) new Point() { X = centrePoint.X + (length / -2.0), Y = centrePoint.Y + (depth / 2.0), Z = centrePoint.Z + (height / 2.0) }); //2 vertices.Add((RenderPoint) new Point() { X = centrePoint.X + (length / -2.0), Y = centrePoint.Y + (depth / -2.0), Z = centrePoint.Z + (height / 2.0) }); //3 vertices.Add((RenderPoint) new Point() { X = centrePoint.X + (length / 2.0), Y = centrePoint.Y + (depth / -2.0), Z = centrePoint.Z + (height / 2.0) }); // Bottom face (normal to global z, -) //4 vertices.Add((RenderPoint) new Point() { X = centrePoint.X + (length / 2.0), Y = centrePoint.Y + (depth / 2.0), Z = centrePoint.Z + (height / -2.0) }); //5 vertices.Add((RenderPoint) new Point() { X = centrePoint.X + (length / 2.0), Y = centrePoint.Y + (depth / -2.0), Z = centrePoint.Z + (height / -2.0) }); //6 vertices.Add((RenderPoint) new Point() { X = centrePoint.X + (length / -2.0), Y = centrePoint.Y + (depth / -2.0), Z = centrePoint.Z + (height / -2.0) }); //7 vertices.Add((RenderPoint) new Point() { X = centrePoint.X + (length / -2.0), Y = centrePoint.Y + (depth / 2.0), Z = centrePoint.Z + (height / -2.0) }); List <Face> faces = new List <Face>(); // Top face (normal to global z, +): 0, 1, 2, 3 faces.Add(new Face() { A = 0, B = 1, C = 2, D = 3 }); // Bottom face (normal to global z, -): 4, 5, 6, 7 faces.Add(new Face() { A = 4, B = 5, C = 6, D = 7 }); // Right face (normal to global x, +): 0, 3, 5, 4 faces.Add(new Face() { A = 0, B = 3, C = 5, D = 4 }); // Left face (normal to global x, -): 2, 1, 7, 6 faces.Add(new Face() { A = 2, B = 1, C = 7, D = 6 }); // Front face (normal to global y, +): 1, 0, 4, 7 faces.Add(new Face() { A = 1, B = 0, C = 4, D = 7 }); // Rear face (normal to global y, -): 3, 2, 6, 5 faces.Add(new Face() { A = 3, B = 2, C = 6, D = 5 }); return(new RenderMesh() { Faces = faces, Vertices = vertices }); }
public static BH.oM.Graphics.RenderMesh RenderMesh(this Sphere sphere, RenderMeshOptions renderMeshOptions = null) { if (sphere == null) { BH.Engine.Base.Compute.RecordError("Cannot compute the mesh of a null sphere."); return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); BH.Engine.Base.Compute.RecordNote("RenderMesh for sphere still doesn't work properly and needs to be finished. A cube is output instead of a sphere."); double radius = sphere.Radius; // // - Sphere still doesn't work properly, for now just return a little cube instead of a sphere. Cuboid cuboid = BH.Engine.Geometry.Create.Cuboid(BH.Engine.Geometry.Create.CartesianCoordinateSystem(sphere.Centre, BH.Engine.Geometry.Create.Vector(1, 0, 0), BH.Engine.Geometry.Create.Vector(0, 1, 0)), radius, radius, radius); return(cuboid.RenderMesh(renderMeshOptions)); // // - WIP Code for sphere mesh. int nLongitude = 6; // Number of vertical lines. int nLatitude = nLongitude / 2; // Number of horizontal lines. A good sphere mesh has about half the number of longitude lines than latitude. double DEGS_TO_RAD = Math.PI / 180; int numVertices = 0; int p, s; double x, y, z; int nPitch = nLongitude + 1; double interLatitudeAngle = (180 / (nLatitude + 1)); interLatitudeAngle = interLatitudeAngle * DEGS_TO_RAD; double interLongitudeAngle = (360 / nLongitude); interLongitudeAngle = interLongitudeAngle * DEGS_TO_RAD; Point centrePoint = sphere.Centre; // ------- Generate all points -------- // List <Point> allPoints = new List <Point>(); Point top = new Point() { X = sphere.Centre.X, Y = sphere.Centre.Y, Z = sphere.Centre.Z + radius }; allPoints.Add(top); for (p = 1; p < nLatitude + 1; p++) // Generate all "intermediate vertices" { double pitchAngleFromZ = interLatitudeAngle * p; z = centrePoint.Z + radius * Math.Cos(pitchAngleFromZ); for (s = 0; s < nLongitude + 1; s++) { x = centrePoint.X + radius * Math.Cos(s * interLongitudeAngle); y = centrePoint.Y + radius * Math.Sin(s * interLongitudeAngle); allPoints.Add(new Point() { X = x, Y = y, Z = z }); } } Point bottom = new Point() { X = sphere.Centre.X, Y = sphere.Centre.Y, Z = sphere.Centre.Z - radius }; allPoints.Add(bottom); // ------- Generate all faces -------- // List <Face> allFaces = new List <Face>(); // Square faces between intermediate points for (int lat = 1; lat < nLatitude; lat++) { for (int lon = 1; lon < nLongitude + 1; lon++) { Face face = new Face() { A = lon * lat + nLongitude * (lat - 1), B = lon * lat + 1 + nLongitude * (lat - 1), C = lon * lat + nLongitude + nLongitude * (lat - 1) + 2, D = lon * lat + nLongitude + nLongitude * (lat - 1) + 1, }; allFaces.Add(face); } } //// Triangle faces between top/bottom points and the intermediate points //int offLastVerts = 2 + (nLatitude * (nLongitude - 1)); //for (s = 0; s < nLatitude; s++) //{ // j = (s == nLatitude - 1) ? -1 : s; // allFaces.Add(new Face() { A = 0, B = (j + 2) + 2, C = (s + 1) + 2 }); // allFaces.Add(new Face() { A = 1, B = (s + 1) + offLastVerts, C = (j + 2) + offLastVerts }); //} //return null; return(new RenderMesh() { Faces = allFaces, Vertices = allPoints.Select(pt => (RenderPoint)pt).ToList() }); }
public static BH.oM.Graphics.RenderMesh RenderMesh(this Extrusion extrusion, RenderMeshOptions renderMeshOptions = null) { if (extrusion == null) { BH.Engine.Base.Compute.RecordError("Cannot compute the mesh of a null extrusion."); return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); Line line = extrusion.Curve as Line; Polyline polyline = extrusion.Curve as Polyline; if (line == null && polyline == null) { polyline = Compute.IRationalise(extrusion.Curve, renderMeshOptions); // try to rationalise the extrusion profile } if (line == null && polyline == null) { BH.Engine.Base.Compute.RecordError($"Calling RenderMesh for {nameof(Extrusion)} currently works only if the {nameof(Extrusion.Curve)} is composed of linear segments."); return(null); } List <Face> faces = new List <Face>(); List <Point> points = new List <Point>(); if (line != null) { points.Add(new Point() { X = line.Start.X, Y = line.Start.Y, Z = line.Start.Z }); points.Add(new Point() { X = line.End.X, Y = line.End.Y, Z = line.End.Z }); points.Add(new Point() { X = line.End.X + extrusion.Direction.X, Y = line.End.Y + extrusion.Direction.Y, Z = line.End.Z + extrusion.Direction.Z }); points.Add(new Point() { X = line.Start.X + extrusion.Direction.X, Y = line.Start.Y + extrusion.Direction.Y, Z = line.Start.Z + extrusion.Direction.Z }); faces.Add(new Face() { A = 0, B = 1, C = 2, D = 3 }); return(new RenderMesh() { Faces = faces, Vertices = points.Cast <RenderPoint>().ToList() }); } RenderMesh bottomCap = null; RenderMesh topCap = null; if (polyline != null) { points.AddRange(polyline.ControlPoints); points.AddRange(polyline.ControlPoints.Select(p => new Point() { X = p.X + extrusion.Direction.X, Y = p.Y + extrusion.Direction.Y, Z = p.Z + extrusion.Direction.Z })); int faceNo = polyline.ControlPoints.Count() - 1; for (int i = 0; i < faceNo; i++) { int add = 0;//extrusion.Curve.IIsClosed() ? 1 : 0; faces.Add(new Face() { A = i, B = i + 1, C = polyline.ControlPoints.Count() + (i + 1) + add, D = polyline.ControlPoints.Count() + i + add }); } if (extrusion.Curve.IIsClosed() && extrusion.Capped) { Polyline bottomBoundary = extrusion.Curve.IRationalise(renderMeshOptions); if (bottomBoundary == null) { Base.Compute.RecordNote("Mesh of Extrusion caps still not implemented for extrusion defined with a curve of this type."); } else { bottomCap = Create.PlanarSurface(bottomBoundary).RenderMesh(renderMeshOptions); Polyline topBoundary = bottomBoundary.Translate(extrusion.Direction); topCap = Create.PlanarSurface(topBoundary).RenderMesh(renderMeshOptions); } } RenderMesh renderMesh = new RenderMesh() { Vertices = points.Select(pt => (RenderPoint)pt).ToList(), Faces = faces }; if (bottomCap != null) { renderMesh = renderMesh.JoinRenderMeshes(bottomCap); } if (topCap != null) { renderMesh = renderMesh.JoinRenderMeshes(topCap); } return(renderMesh); } BH.Engine.Base.Compute.RecordError($"Calling RenderMesh for {nameof(Extrusion)} currently works only if the {nameof(Extrusion.Curve)} is composed of linear segments."); return(null); }
public static SpeckleObject SpeckleRepresentation(IBHoMObject bhomObject, RenderMeshOptions renderMeshOptions = null) { renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); SpeckleObject speckleRepresentation = null; if (bhomObject is CustomObject) { return(null); } // See if the object contains a custom Mesh Representation in its Fragments. Mesh meshRepresentation = null; RenderMesh renderMesh = null; if (bhomObject != null) { RenderMesh renderMeshObj = null; bhomObject.TryGetRendermesh(out renderMeshObj); if (renderMeshObj != null) { meshRepresentation = new Mesh() { Faces = renderMeshObj.Faces, Vertices = renderMeshObj.Vertices.Select(v => v.Point).ToList() } } ; } if (renderMesh != null) { meshRepresentation = new Mesh() { Faces = renderMesh.Faces, Vertices = renderMesh.Vertices.Select(v => new oM.Geometry.Point() { X = v.Point.X, Y = v.Point.Y, Z = v.Point.Z }).ToList() }; return(meshRepresentation.ToSpeckle()); } if (meshRepresentation != null) { return(meshRepresentation.ToSpeckle()); } // See if there is a custom BHoM Geometry representation for that BHoMObject. // If so, attempt to convert it to Speckle. IGeometry geometricalRepresentation = null; try { geometricalRepresentation = BH.Engine.Representation.Compute.IGeometricalRepresentation(bhomObject, renderMeshOptions.RepresentationOptions); } catch { } // If found, attempt to convert the BHoM Geometrical representation of the object to Speckle geometry. if (geometricalRepresentation != null) { speckleRepresentation = geometricalRepresentation.IToSpeckle(); } // If the convert of the base geometry to Speckle Geometry didn't work, // try to obtain a BHoM RenderMesh of the geometrical representation, then convert it to a Speckle mesh. if (speckleRepresentation == null) { try { // Do not use the interface method IRenderMesh here. That one re-computes the geometrical representation. renderMesh = BH.Engine.Representation.Compute.RenderMesh(geometricalRepresentation as dynamic); } catch { } if (renderMesh != null) { speckleRepresentation = Speckle.Convert.ToSpeckle(renderMesh); } } return(speckleRepresentation); } }
public static BH.oM.Graphics.RenderMesh RenderMesh(this PlanarSurface planarSurface, RenderMeshOptions renderMeshOptions = null) { if (planarSurface == null) { BH.Engine.Base.Compute.RecordError("Cannot compute the mesh of a null planar surface."); return(null); } renderMeshOptions = renderMeshOptions ?? new RenderMeshOptions(); Polyline externalBoundary = planarSurface.ExternalBoundary.IRationalise(renderMeshOptions); if (externalBoundary == null) { BH.Engine.Base.Compute.RecordError($"Meshing for {nameof(PlanarSurface)} works only if the {nameof(planarSurface.ExternalBoundary)} is of type {nameof(Polyline)}"); return(null); } List <Polyline> internalBoundaries = planarSurface.InternalBoundaries.Select(c => c.IRationalise(renderMeshOptions)).ToList(); if (internalBoundaries.Count != internalBoundaries.Count) { BH.Engine.Base.Compute.RecordError($"Meshing for {nameof(PlanarSurface)} works only if all of the {nameof(planarSurface.InternalBoundaries)} are of type {nameof(Polyline)}"); return(null); } List <Polyline> polylines = BH.Engine.Geometry.Triangulation.Compute.DelaunayTriangulation(externalBoundary, internalBoundaries); List <RenderMesh> singleFacesMeshes = new List <RenderMesh>(); foreach (Polyline poly in polylines) { RenderMesh singleFaceMesh = new RenderMesh(); singleFaceMesh.Vertices.AddRange(poly.ControlPoints.Select(p => (RenderPoint)p)); singleFaceMesh.Faces.Add(new Face() { A = 0, B = 1, C = 2 }); singleFacesMeshes.Add(singleFaceMesh); } return(singleFacesMeshes.JoinRenderMeshes()); }
// Fallback private static BH.oM.Graphics.RenderMesh RenderMesh(this IGeometry geom, RenderMeshOptions renderMeshOptions = null) { throw new MissingMethodException($"Could not find a method to compute the {nameof(BH.oM.Graphics.RenderMesh)} of {geom.GetType().Name}."); }