@@ -21,37 +21,31 @@ struct QueryPolygon
2121end
2222
2323"""
24- get_polygon(pts ; ratio=0.1)
24+ get_polygon(points::AbstractArray ; ratio::Bool =0.1)
2525
2626Description:
2727---
28- Get the polygon from the given points. `pts ` is a 2xN array, and `ratio` is the
28+ Get the polygon from the given points. `points ` is a 2xN array, and `ratio` is the
2929parameter for the concave hull. The default value is 0.1.
30+
31+ Example:
32+ ---
33+ ```julia
34+ polygon_xy = [0 0; 1 0; 1 1; 0 1]' # 2xN array
35+ polygon = get_polygon(polygon_xy, ratio=1) # polygon.py_xy to visualize
36+ ```
3037"""
3138function get_polygon (points:: AbstractArray ; ratio:: Real = 0.1 )
3239 # inputs checking
3340 n, m = size (points)
3441 n == 2 || error (" points must be a 2xN array" )
3542 m >= 3 || error (" at least 3 points are required" )
3643 ratio > 0 || error (" ratio must be positive" )
37- allow_holes = 0
38- pts = Array {Float64} (points)
39-
40- # convert to GEOS datatype
41- gpts = LibGEOS. MultiPoint ([pts[:, i] for i in axes (pts, 2 )])
42- ctx = LibGEOS. get_context (gpts)
43- ptr = LibGEOS. GEOSConcaveHullByLength_r (ctx, gpts, ratio, allow_holes)
44- conc = LibGEOS. geomFromGEOS (ptr)
45- conc == C_NULL && error (" LibGEOS: Error in GEOSConvexHull" )
46-
47- # convert back to julia datatype
48- ob_outer = LibGEOS. exteriorRing (conc)
49- cs_outer = LibGEOS. getCoordSeq (ob_outer)
50- xs_outer = LibGEOS. getX (cs_outer)
51- ys_outer = LibGEOS. getY (cs_outer)
52- xy = vcat (permutedims (xs_outer), permutedims (ys_outer))
53-
54- return QueryPolygon (xy, shapely. Polygon (xy' ))
44+ # use shapely to get the polygon
45+ py_points = shapely. MultiPoint (np. array (points' ))
46+ poly = shapely. concave_hull (py_points, ratio= ratio, allow_holes= false )
47+ xy = pyconvert (Array, np. array (poly. exterior. xy)) # get the exterior points of the polygon
48+ return QueryPolygon (xy, poly)
5549end
5650
5751"""
@@ -68,8 +62,8 @@ Example:
6862```julia
6963polypon_xy = [0 0; 1 0; 1 1; 0 1]' # 2xN array
7064polygon = get_polygon(polygon_xy, ratio=1) # polygon.py_xy to visualize
71- particle_in_polygon (polygon, 0, 0) # check points (0, 0) and return false
72- particle_in_polygon (polygon, 0, 0, edge=true) # check points (0, 0) and return true
65+ pip_query (polygon, 0, 0) # check points (0, 0) and return false
66+ pip_query (polygon, 0, 0, edge=true) # check points (0, 0) and return true
7367```
7468"""
7569function pip_query (
@@ -92,10 +86,12 @@ array, where each column represents a point (x, y). If `edge` is set to true, it
9286the points are on the edge of the polygon as well.
9387
9488Example:
89+ ---
9590```julia
9691polygon_xy = [0 0; 1 0; 1 1; 0 1]' # 2xN array
9792polygon = get_polygon(polygon_xy, ratio=1) # polygon.py_xy to visualize
9893pip_query(polygon, [0 0; 0.5 0.5; 1 1], edge=true) # returns [true, true, true]
94+ ```
9995"""
10096function pip_query (
10197 polygon:: QueryPolygon ,
@@ -129,10 +125,12 @@ where each column represents a point (x, y). If `edge` is set to true, it checks
129125points are on the edge of the mesh as well.
130126
131127Example:
128+ ---
132129```julia
133130stl_file = "path/to/your/file.stl"
134131points = [0 0; 0.5 0.5; 1 1]'
135132pip_query(stl_file, points, edge=true)
133+ ```
136134"""
137135function pip_query (
138136 stl_file:: String ,
@@ -164,3 +162,70 @@ function pip_query(
164162 tmp = py_pip (stl_file, py_points, trimesh, shapely)
165163 return pyconvert (Vector{Bool}, tmp)
166164end
165+
166+ """
167+ pip_query(mesh::Py, points::AbstractMatrix; edge::Bool=false)
168+
169+ Description:
170+ ---
171+ Determine whether a set of points is inside a 3D mesh defined by a Python object. The input
172+ `mesh` should be a Python object representing the mesh (`trimesh`), and `points` should be
173+ a 2xN array where each column represents a point (x, y). If `edge` is set to true, it checks
174+ if the points are on the edge of the mesh as well.
175+
176+ Example:
177+ ---
178+ ```julia
179+ mesh = trimesh.load("path/to/your/file.stl", force="mesh")
180+ points = [0 0; 0.5 0.5; 1 1]'
181+ pip_query(mesh, points, edge=true)
182+ ```
183+ """
184+ function pip_query (
185+ mesh :: Py ,
186+ points :: AbstractMatrix ;
187+ edge :: Bool = false
188+ )
189+ size (points, 1 ) == 2 || error (" points must be a 2xN array" )
190+ py_points = shapely. points (points' )
191+ if edge
192+ @pyexec """
193+ def py_pip(mesh, py_points, trimesh, shapely):
194+ tris2d = mesh.triangles[:, :, :2]
195+ region = shapely.unary_union([shapely.Polygon(t) for t in tris2d])
196+ mask = shapely.covers(region, py_points)
197+ return mask
198+ """ => py_pip
199+ else
200+ @pyexec """
201+ def py_pip(mesh, py_points, trimesh, shapely):
202+ tris2d = mesh.triangles[:, :, :2]
203+ region = shapely.unary_union([shapely.Polygon(t) for t in tris2d])
204+ mask = shapely.within(py_points, region)
205+ return mask
206+ """ => py_pip
207+ end
208+ tmp = py_pip (mesh, py_points, trimesh, shapely)
209+ return pyconvert (Vector{Bool}, tmp)
210+ end
211+
212+ """
213+ pip_query(stl_model::STLInfo, points::AbstractMatrix; edge::Bool=false)
214+
215+ Description:
216+ ---
217+ Determine whether a set of points is inside a 3D mesh defined by a 'STLInfo'. The input
218+ `stl_model` should be initiated by function `loadmesh(stl_file)`, and `points` should be
219+ a 2xN array where each column represents a point (x, y). If `edge` is set to true, it checks
220+ if the points are on the edge of the mesh as well.
221+
222+ Example:
223+ ---
224+ ```julia
225+ stl_model = loadmesh("path/to/your/file.stl")
226+ points = [0 0; 0.5 0.5; 1 1]'
227+ pip_query(stl_model, points, edge=true)
228+ ```
229+ """
230+ pip_query (stl_model:: STLInfo , points:: AbstractMatrix ; edge:: Bool = false ) = pip_query (
231+ stl_model. mesh, points; edge= edge)
0 commit comments