I'm trying to convert a polygonal 3D mesh into a series of topographic curves that represent the part of the mesh at a specific height for every interval. So far, I've come up with the idea to intersect a horizontal plane with the mesh and get the intersection curve(s). So for this mesh:
I'd intersect a plane repeatedly at a set interval of precision:
and etc.
While this is straightforward to do visually and in a CAD application, I'm completely lost doing this programmatically. How could I achieve calculating this in a programming environment/ what algorithms can I look into to achieve this?
I'm programming in an STL C++ environment (with Boost), loading .obj meshes with this simple loader, and need simple cartesian 2D points to define the output curve.
An option is to process all the faces in turn and for every face determine the horizontal planes that traverses them. For a given plane and face, check all four vertexes in turn and find the changes of sign (of Zvertex - Zplane). There will be exactly two such changes, defining an edge that belongs to a level curve. (Exceptionally you can find four changes of sign, which occurs when the facet isn't planar - join the points in pairs.)
Every time you find an intersection point, you tag it with the (unique) index of the plane and the (unique) index of the edge that was intersected; you also tag it with the index of the other edge that was intersected in that face.
By sorting on the plane index, you can group the intersections per plane.
For a given plane, using a hash table, you can follow the chain of intersections, from edge to edge.
This gives you the desired set of curves.
Related
In my current c++ program I am dealing with a plane that is intersected by several other planes. I want to find the polygon formed by the lines that define the intersections of the planes. For simplicity and computation speed, it seems like my best bet is to get the lines that form the intersections and then work out the polygon in 2d on the surface of the plane. Does anyone have an idea how to translate the lines(represented by a position and a direction vector) onto the plane and the final polygon back into 3d?
In general, this isn't possible to do. The simplest counterexample is the intersection of two planes where the two centers overlap. Viewing it edge-on, it would look like a plus sign. There is no polygon that results from this intersection; a line segment, yes, but no polygon. If you want to draw the resulting polygon, then it needs to be convex, as well which puts more constraints on the allowable intersection configurations.
What would be recommended ways to generate surface meshes of a particular kind of body given the following?
The geometric body is an extruded 3D "tube" segment. The tube segment has the following properties:
At each value of X, the cross-section is always a simple polygon in the Y-Z plane
The polygons are not guaranteed to be convex
The polygons are not necessarily constant as X is traversed; they smoothly dilate and/or change shape, and the areas of the polygons smoothly vary
The centroids of each X = const polygon, if connected together with simple line segments, would form a very smooth, well behaved "thread" with at most gentle curvature, no sharp bends, folds, or loops, etc.
The surface section is capped by the planar cross-sectional polygons at X = X_start and X = X_end
Objective:
Generate a triangulated surface mesh of the tube surface, respecting the fact that it is bounded at the start and end by flat, planar cross-sectional surfaces
The mesh should be of the tube, not a convex hull of the tube
If the tube surface mesh maintains the property that there is a flat simple polygonal cross-section formed by the vertices at X = X_start and X = X_end, then I have existing code which can mesh the end caps; the real problem I'm trying to solve is to get the 3D tube surface mesh generated. If the solution also can generate the end caps, that's fine too. However, the end cap surfaces need to be identifiable as such for output purposes.
Once the mesh is generated, it needs to be written in a format like OFF, which I think I can handle based on code included with CGAL, examples, etc. The point here is that I don't need to be able further process the mesh (e.g. deformations, add/remove points) programmatically after it is generated.
Known inputs and properties:
I have the polygonal cross-section tube surface vertices at an arbitrary number of X = const stations between X_start and X_end ; I can control the spacing in the X direction as necessary when I create/import the points
The vertices lie exactly on the tube surface and are not corrupted by any noise, joggles, sampling, approximations, etc.
I do not have any guarantees about the relative position of vertices forming each cross-sectional polygon, other than that the polygon vertices are oriented clockwise
I can generate normals for the polygonal vertices in terms of their Y-Z components, but I don't have a priori information about their normal components in the X direction
I can generate any number of vertices on the end caps if necessary
Right now the vertices are 3-space floating-point coordinate values, but if it could somehow help, I could turn each cross-section into a formal CGAL 2D arrangement
Estimated number of vertices would likely be less than 1000, definitely less than say 15K. Processing time is not a concern.
Ideals:
Ideally, the surface mesh would just use the vertices I have, without subtracting or moving any of them, but this is not a hard constraint so long as they are "close"
I need simple polygonal vertices at X_start and X_end so I can cap the surfaces as intended
Initially, CGAL's Poisson Surface Reconstruction method seemed promising, but in the end it seems like it leads to a processing pipeline that might smear the vertices I have; additionally, I don't have full 3D normal information for the points other than the end caps. Moreover, the method would seem to have issues with the sharp, distinct cross-section terminal face surfaces. Maybe I could get around the latter by putting in a bunch of benignly false vertices to extend and terminate the tube, then filter out parts of the triangulation I don't need, but there's no guarantee that the vertices at X_start and X_end would remain, and I would have to "fix-up" the triangulation crossing those planes, which seems non-trivial.
Another possibility might be to compute a full 3D volume mesh using CGAL's 3D mesh generator, but just write out the portion comprising the surface mesh. Is this reasonable? If I could retain the original input vertices, and this overall approach is reasonable, I could filter as I wrote out the triangulation to distinguish between the faces forming the end caps vs. the tube surface.
I also saw this SO question Representing a LiDAR surface using the 3D Delaunay Triangulation as basis? which seems to have some similarities (trying to just retain the input points, and some foreknowledge of the surface properties), but in the end I think my use case is too different.
Can someone tell me the best way to estimate the normal at a point on CAD STL geometry?
This is not exactly a question on code, but rather about efficiency and approach.
I have used an approach in which I compare the point whose normal needs to be estimated with all the triangles in the mesh and check to see if it lies inside the triangle using the barycentric coordinates test. (If the value of each barycentric coordinate lies between 0 and 1, the point lies inside.) This post explains it
https://math.stackexchange.com/questions/4322/check-whether-a-point-is-within-a-3d-triangle
Then I compute the normal of that triangle to get the point normal.
The problem with my approach is that, if I have some 1000 points, and if the mesh has say, 500 triangles, that would mean doing some 500X1000 checks. This takes a lot of time.
Is there an efficient data structure or approach I could use, to pinpoint the right triangle? Or a library that could get the work done?
A relatively easy solution is by using a grid: decompose the space in a 3D array of voxels, and for every voxel keep a list of the triangles that interfere with it.
By interfere, I mean that there is a nonempty intersection between the voxel and the bounding box of the triangle. (When you know the bounding box, it is straight forward to tell what voxels it covers.)
When you want to test a point, find the voxel it belongs to and compare to the list of triangles. You will achieve a speedup equal to N/M, where M is the average number of triangles per voxel.
The voxel size should be chosen carefully. Too small will result in a too big data structure; too large will make the method ineffective. If possible, adjust to "a few" triangles per voxel. (Use the average triangle size - square root of double area - as a starting value.)
For better efficiency, you can compute the exact intersections between the triangles and the voxels, using a 3D polygon clipping algorithm (rather than a mere bounding box test), but this is more complex to implement.
Here is another geometric problem:
I have created an 3-dimensional triangulated iso-surface of a point cloud using the marching cubes algorithm. Then I intersect this iso-surface with a plane and get a number of line segments that represent the contour lines of the intersection.
Is there any possibility to sort the vertices of these line segments clockwise so that I can draw them as a closed path and do a flood fill?
Thanks in advance!
It depends on how complex your isosurface is, but the simplest thing I can think of that might work is:
For each point, project to the plane. This will give you a set of points in 2d.
Make sure these are centered, via a translation to the centroid or center of the bounding box.
For each 2d point, run atan2 and get an angle. atan2 just puts things in the correct quadrant.
Order by that angle
If your isosurface/plane is monotonically increasing in angle around the centroid, then this will work fine. If not, then you might need to find the 2 nearest neighbors to each point in the plane, and hope that that makes a simple loop. In face, the simple loop idea might be simpler, because you don't need to project and you don't need to compute angles - just do everything in 3d.
I have a set of points and i want to draw a curve which should be approximated to original curve.
Let say ,in hawk-eye system(used in cricket) i have a set ofco-ordinates of ball during the entire flight of ball , now how can i draw such a curve going through ball's space co-ordinates and looks appromixately to original curve
one method i thought its to get a large number of points such that every two point
is very close to each other and then draw a straight light between them
Curves are almost always rendered in four steps:
Approximate or interpolate a set of points using a curve or spline algorithm. Choices may include:
Cubic splines, which pass through all of the data points and produce a smooth curve
Bézier curves, which do not pass through all the points, but which lie within the envelope of the consecutive groups of 4 points surrounding each curve section.
Hermite curves, which are defined by a set of points, and a set of tangent vectors: you would need to generate the set of tangent vectors somehow in order to use this sort of curve.
(and probably more that I've forgotten)
Convert whichever representation you chose to a Bézier Curve: this can be achieved by a simple matrix transformation from other curve types.
Repeatedly subdivide the Bézier curve: the control points tend to approximate the curve.
Draw the control points of the subdivided curve, joined by a straight line.
If you go straight for the Bézier curve, which is probably the easiest, then there are some very simple and elegant methods of subdividing it.
I highly recommend Catmull-Rom splines for this purpose, they are based on Hermite curves. Rather than using 2 points and 2 tangents, it uses the four adjacent data points to interpolate making it better suited/simpler for motion path upsampling.