Convert mesh to polygon in python - python

I have a mesh and want to convert it into a polygon. I did some google search and found most answer on converting polygon to mesh. I want to do the opposite.Is there any library or any idea on how to achieve it

Well you can use the Python FME library to take input as a mesh object and return a polygon
import fmeobjects
class MeshToPolygons(object):
def input(self, feature):
mesh = feature.getGeometry()
if isinstance(mesh, fmeobjects.FMEMesh):
vertices = mesh.getVertices()
for part in mesh:
indices = part.getVertexIndices()
if indices:
boundary = fmeobjects.FMELine([vertices[i] for i in indices])
feature.setGeometry(fmeobjects.FMEPolygon(boundary))
self.pyoutput(feature)
If the above doesn't help, you can also check out the python TriMesh library. You could load the object as mesh using
trimesh.load(file_obj, file_type=None, resolver=None, force=None, **kwargs)
Return type: Trimesh, Path2D, Path3D, Scene
Returns: geometry – Loaded geometry as trimesh classes
Now convert the mesh object into a sequence of connected points. After that you can use
trimesh.path.polygons.paths_to_polygons(paths, scale=None)
Return type: (p,) list
Returns: polys – Filled with Polygon or None
Hope it helps

Related

Sorting the mesh vertices in Blender

I'm creating an application that requires the vertices array of the mesh to be sorted in a particular way, to access them more easily: from left to right then downwards to upwards (in the xy plane) like this:
[indexes][1]
My code successfully does that, but the resulting mesh is all glitched out:
[resulting mesh][2]
I think it's likely that the new edges are causing the problem, but haven't found a way to fix them. Here's the mesh sorting code I wrote:
# This example assumes we have a mesh object selected
import bpy
import bmesh
#Weights for order. Left>>Right Down>>Up
def order(vector):
return vector[0]+200*vector[1]
# Get the active mesh
me = bpy.context.object.data
verts=[]
# Get a BMesh representation
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
#Convert current verts to tuple list (x,y,z)
i=0
for v in bm.verts:
verts.append((v.co.x,v.co.y,v.co.z))
# Sort the verts.
verts.sort(key=order)
#Assign the sorted vertices to the mesh
i=0
for v in bm.verts:
v.co.x,v.co.y,v.co.z = verts[i]
i+=1
#Debugging edges (possible problem?)
for v in bm.edges:
if i<10:
print(v)
i+=1
# Finish up, write the bmesh back to the mesh
bm.verts.index_update()
bm.to_mesh(me)
#bmesh.update_edit_mesh(me)
bm.free() # free and prevent further access
Is there any way to rearrange the edges? Or any post processing trick I can do on the mesh, anything helps.
Thanks in advance.
[1]: https://i.stack.imgur.com/iuoBc.png
[2]: https://i.stack.imgur.com/atxvF.png

splitting circle into two using LineString Python Shapely

I have created a circle using Shapely and would like to split it into two using LineString.
I created the circle as follows
from functools import partial
import pyproj
from shapely import geometry
from shapely.geometry import Point, Polygon, shape, MultiPoint, LineString, mapping
from shapely.ops import transform, split
radius = 92600
lon = 54.08
lat = 17.05
local_azimuthal_projection = "+proj=aeqd +R=6371000 +units=m +lat_0={} +lon_0={}".format(
lat, lon
)
wgs84_to_aeqd = partial(
pyproj.transform,
pyproj.Proj("+proj=longlat +datum=WGS84 +no_defs"),
pyproj.Proj(local_azimuthal_projection),
)
aeqd_to_wgs84 = partial(
pyproj.transform,
pyproj.Proj(local_azimuthal_projection),
pyproj.Proj("+proj=longlat +datum=WGS84 +no_defs"),
)
center = Point(float(lon), float(lat))
point_transformed = transform(wgs84_to_aeqd, center)
buffer = point_transformed.buffer(radius)
# Get the polygon with lat lon coordinates
circle_poly = transform(aeqd_to_wgs84, buffer)
For the line Splitter I have the following:
splitter = LingString([Point(54.79,16.90), Point(53.56,16.65)])
Now I want to see the two split shapes so I used split function.
result = split(circle_poly, splitter)
However, this only results the same circle and not two shapes.
At the end I would like to use one section of the split to form another shape.
To split a circle or a polygon, you can use spatial difference operation with another polygon. Shapely does not allow the use of line to do so.
"Shapely can not represent the difference between an object and a lower dimensional object (such as the difference between a polygon and a line or point) as a single object."
See document:
In your case, you can build two polygons that have the line as the common edges.
Make sure that the 2 polygons together are big enough to cover the whole polygon you are splitting. Then you use that polygons to do the job.
If you want crude results from the difference operation,
you can turn the line into a slim polygon by buffer operation, and use it.
For the second approach, here is the relevant code:
the_line = LineString([(54.95105, 17.048144), (53.40473921, 17.577181)])
buff_line = the_line.buffer(0.000001) #is polygon
# the `difference` operation between 2 polygons
multi_pgon = circle_poly.difference(buff_line)
The result is a multi-polygon geometry object.

how to make an open stl file watertight

Newbie here!
I have an STL file which is not watertight and the gap is quite big to repair with the close vertex of the trimesh.
I tried with open3d by following this but I have the following error: "ValueError: vector too long"..
Is there any way to make the mesh watertight? I need to calculate the CoM and Inertia matrix but the values would not be correct if my mesh is not watertight/a closed surface.
For the open3d, firstly I uploaded the stl file, I converted it to numpy and then I used the following code:
pcd = o3d.geometry.PointCloud()
pcd.points = o3d.utility.Vector3dVector(DataNP)
o3d.io.write_point_cloud("testinggggg.ply", pcd)
poisson_mesh = o3d.geometry.TriangleMesh.create_from_point_cloud_poisson(pcd, depth=8, width=0, scale=1.1, linear_fit=False)[0]
bbox = pcd.get_axis_aligned_bounding_box()
p_mesh_crop = poisson_mesh.crop(bbox)
o3d.io.write_triangle_mesh("output_testinggggg.ply", dec_mesh)
Any help is highly appreciated!
I have managed to make the mesh watertight. I will post here in case anyone is having troubles in the future with it.
My mesh was actually made of 2 smaller meshes, so I had to first merge them together and then use the VTK library to clean the mesh and fill the holes. This made my mesh watertight and I could calculate everything I needed.
This is the code:
input1 = vtk.vtkPolyData()
input2 = vtk.vtkPolyData()
input1.DeepCopy(Data1.GetOutput())
input2.DeepCopy(Data2.GetOutput())
# Append the two meshes
appendFilter = vtk.vtkAppendPolyData()
appendFilter.AddInputData(input1)
appendFilter.AddInputData(input2)
appendFilter.Update()
# Remove any duplicate points.
cleanFilter = vtk.vtkCleanPolyData()
cleanFilter.SetInputConnection(appendFilter.GetOutputPort())
cleanFilter.Update()
# newData = cleanFilter
fill = vtk.vtkFillHolesFilter()
fill.SetInputConnection(appendFilter.GetOutputPort())
fill.SetHoleSize(100)
fill.Update()

Folium PolyLine not showing up on map - folium 0.7.0 with python 3.6 (anaconda) in Jupyter notebook

I have a folium map of a neighborhood in New York City generated using the following code:
m = folium.Map(location=[40.7035, -73.990],
zoom_start=16.5,
tiles='cartodbpositron')
I then try to add lines connecting points on the map using folium.PolyLine(), but even though I see them listed when I call m._children, they don't show up on the map.
Here's the code to create the lines, where G is a networkx graph:
for x, y in G.edges():
points = [nx.get_node_attributes(G, 'loc')[x], nx.get_node_attributes(G, 'loc')[y]]
egde = folium.PolyLine(locations=points, weight=5, color='red')
edge.add_to(m)
A sample point:
[(-73.986635, 40.703988), (-73.988683, 40.702674)]
Output of m.children (first few lines):
OrderedDict([('cartodbpositron',
<folium.raster_layers.TileLayer at 0x12279feb8>),
('poly_line_ae5785771a2148c5a8559cb0085b10a4',
<folium.vector_layers.PolyLine at 0x122892128>),
('poly_line_ee73b495559940d484064e8c8492eda5',
<folium.vector_layers.PolyLine at 0x1229734a8>),
('poly_line_415a7ed70a2a425e876c8a6711408a6a', ...
Any idea what I might be doing wrong?
This is kind of odd that folium polyline expects coordinates in [latitude, longitude] format, whereas in general accepted format is [longitude, latitude].
Let's take an example:
I'm assuming you are using OSRM to get geometries.
OSRM geometries returns coordinates in the form of [[longitude,latitude],...].
If you'll directly use them with folium, it'll not show the polyline.
Reverse the geometry coordinates using following function:
def reverse_lon_lat(x):
a = [[p[1], p[0]] for p in x]
return a
and draw the polylines you intend to.

How to convert list of polygon objects to 2D list of coords with Python

I have a list of polygon objects:
[shapely.geometry.polygon.Polygon object at 0x7efa3099f210,
shapely.geometry.polygon.Polygon object at 0x7efa3099f5d0,
shapely.geometry.polygon.Polygon object at 0x7efa30a01410]
I would like to convert these back into a list of 2D coordinates like this:
[[(59.019498746806114, -45.665396889176236),
(59.94899586119081, -45.18051792326192),
(60.264519944473435, -43.49720173548366),
(63.13914992079595, -41.75713765132456)],
[(65.27046115508618, -38.81009751714569),
(66.87400474798349, -35.32763756915183),
(66.59651348548812, -34.479633238363796),
(64.08620000264494, -34.508862817833695)],
[(62.967585829885984, -39.02682594501325),
(58.84847235610258, -41.12579914422148),
(57.972105870186965, -45.614782988871184),
(59.019498746806114, -45.665396889176236)]]
I realize from shapely.geometry import Polygon converts the coordinates into a polygon, however I am trying to do the opposite.
Any advice on how to go about this using Python?
I'm not sure on API, but try
coords = [list(poly.exterior.coords) for poly in poly_list]

Categories

Resources