Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
# go through results to get minimum distance result
for i, close_points, distance, candidate in zip(
np.arange(len(points)),
np.array_split(query_close, query_group),
np.array_split(distance_2, query_group),
candidates):
# unless some other check is true use the smallest distance
idx = distance.argmin()
# if we have multiple candidates check them
if len(candidate) > 1:
# (2, ) int, list of 2 closest candidate indices
idxs = distance.argsort()[:2]
# make sure the two distances are identical
check_distance = distance[idxs].ptp() < tol.merge
# make sure the magnitude of both distances are nonzero
check_magnitude = (np.abs(distance[idxs]) > tol.merge).all()
# check if query-points are actually off-surface
if check_distance and check_magnitude:
# get face normals for two points
normals = mesh.face_normals[np.array(candidate)[idxs]]
# compute normalized surface-point to query-point vectors
vectors = ((points[i] - close_points[idxs]) /
distance[idxs, np.newaxis] ** 0.5)
# compare enclosed angle for both face normals
dots = util.diagonal_dot(normals, vectors)
# take the idx with the most positive angle
idx = idxs[dots.argmax()]
# take the single closest value from the group of values
Raises
-------------
ValueError
If a valid finite- area polygon isn't available
"""
if isinstance(obj, Polygon):
polygon = obj
elif util.is_shape(obj, (-1, 2)):
polygon = Polygon(obj)
elif util.is_string(obj):
polygon = load_wkb(obj)
else:
raise ValueError('Input not a polygon!')
if (not polygon.is_valid or
polygon.area < tol.zero):
raise ValueError('Polygon is zero- area or invalid!')
return polygon
valid : (n, 3) bool
Indicate whether a valid intersection exists
for each input line segment
"""
endpoints = np.asanyarray(endpoints)
plane_origin = np.asanyarray(plane_origin).reshape(3)
line_dir = util.unitize(endpoints[1] - endpoints[0])
plane_normal = util.unitize(np.asanyarray(plane_normal).reshape(3))
t = np.dot(plane_normal, (plane_origin - endpoints[0]).T)
b = np.dot(plane_normal, line_dir.T)
# If the plane normal and line direction are perpendicular, it means
# the vector is 'on plane', and there isn't a valid intersection.
# We discard on-plane vectors by checking that the dot product is nonzero
valid = np.abs(b) > tol.zero
if line_segments:
test = np.dot(plane_normal,
np.transpose(plane_origin - endpoints[1]))
different_sides = np.sign(t) != np.sign(test)
nonzero = np.logical_or(np.abs(t) > tol.zero,
np.abs(test) > tol.zero)
valid = np.logical_and(valid, different_sides)
valid = np.logical_and(valid, nonzero)
d = np.divide(t[valid], b[valid])
intersection = endpoints[0][valid]
intersection = intersection + np.reshape(d, (-1, 1)) * line_dir[valid]
return intersection, valid
# add Path2D and Path3D objects
_append_path(
path=geometry,
name=name,
tree=tree,
buffer_items=buffer_items)
# cull empty or unpopulated fields
# check keys that might be empty so we can remove them
check = ['textures', 'samplers', 'materials', 'images']
for key in check:
if len(tree[key]) == 0:
tree.pop(key)
# in unit tests compare our header against the schema
if tol.strict:
validate(tree)
return tree, buffer_items
def remove_degenerate_faces(self, height=tol.merge):
"""
Remove degenerate faces (faces without 3 unique vertex indices)
from the current mesh.
If a height is specified, it will remove any face with a 2D oriented
bounding box with one edge shorter than that height.
If not specified, it will remove any face with a zero normal.
Parameters
------------
height : float
If specified removes faces with an oriented bounding
box shorter than this on one side.
Returns
"""
# what is the radius of a circle that passes through the perpendicular
# projection of the vector between the two non- shared vertices
# onto the shared edge, with the face normal from the two adjacent faces
radii = mesh.face_adjacency_radius
# what is the span perpendicular to the shared edge
span = mesh.face_adjacency_span
# a very arbitrary formula for declaring two adjacent faces
# parallel in a way that is hopefully (and anecdotally) robust
# to numeric error
# a common failure mode is two faces that are very narrow with a slight
# angle between them, so here we divide by the perpendicular span
# to penalize very narrow faces, and then square it just for fun
parallel = np.ones(len(radii), dtype=np.bool)
# if span is zero we know faces are small/parallel
nonzero = np.abs(span) > tol.zero
# faces with a radii/span ratio larger than a threshold pass
parallel[nonzero] = (radii[nonzero] /
span[nonzero]) ** 2 > tol.facet_threshold
# run connected components on the parallel faces to group them
components = connected_components(
mesh.face_adjacency[parallel],
nodes=np.arange(len(mesh.faces)),
min_len=2,
engine=engine)
return components
# the per- row index of the shortest edge
small = norms.argmin(axis=1)
# the ordered index for the medium and large edge norm
# arranged to reference flattened norms for indexing
MLidx = np.column_stack((small + 1, small + 2)) % 3
MLidx += (np.arange(len(small)) * 3).reshape((-1, 1))
# subtract the two largest edge lengths from each other
diff = np.subtract(*norms.reshape(-1)[MLidx.T])
# mark by sign but keep zero values zero
order = np.zeros(len(norms), dtype=np.int64)
order[diff < tol.merge] = -1
order[diff > tol.merge] = 1
return order
v, vc = v[:, :3], v[:, 3:6]
elif v is not None and v.shape[1] > 3:
# we got a lot of something unknowable
v = v[:, :3]
# vertex texture or None
vt = result['vt']
if vt is not None:
# sometimes UV coordinates come in as UVW
vt = vt[:, :2]
# vertex normals or None
vn = result['vn']
# check will generally only be run in unit tests
# so we are allowed to do things that are slow
if tol.strict:
# check to make sure our subsetting
# didn't miss any vertices or data
assert len(v) == text.count('\nv ')
# make sure optional data matches file too
if vn is not None:
assert len(vn) == text.count('\nvn ')
if vt is not None:
assert len(vt) == text.count('\nvt ')
return v, vn, vt, vc
# triangle edge.
P = np.cross(ray_direction, edge1)
# if determinant is near zero, ray lies in plane of triangle
det = diagonal_dot(edge0, P)
candidates[np.abs(det) < tol.zero] = False
if not candidates.any():
return candidates
# remove previously calculated terms which are no longer candidates
inv_det = 1.0 / det[candidates]
T = ray_origin - vert0[candidates]
u = diagonal_dot(T, P[candidates]) * inv_det
new_candidates = np.logical_not(np.logical_or(u < -tol.zero,
u > (1 + tol.zero)))
candidates[candidates] = new_candidates
if not candidates.any():
return candidates
inv_det = inv_det[new_candidates]
T = T[new_candidates]
u = u[new_candidates]
Q = np.cross(T, edge0[candidates])
v = np.dot(ray_direction, Q.T) * inv_det
new_candidates = np.logical_not(np.logical_or((v < -tol.zero),
(u + v > (1 + tol.zero))))
candidates[candidates] = new_candidates
if not candidates.any():
return candidates
use_tex : bool
If True for textured meshes merge vertices
with identical positions AND UV coordinates.
use_norm : bool
If True meshes with vertex normals defined will
only have vertices merged with identical normal
digits_vertex : None or int
Number of digits to consider for vertex position
digits_norm : int
Number of digits to consider for unit normals
digits_uv : int
Number of digits to consider for UV coordinates
"""
# use tol.merge if digit precision not passed
if not isinstance(digits_vertex, int):
digits_vertex = util.decimal_to_digits(tol.merge)
# if we have a ton of unreferenced vertices it will
# make the unique_rows call super slow so cull first
if hasattr(mesh, 'faces') and len(mesh.faces) > 0:
referenced = np.zeros(len(mesh.vertices), dtype=np.bool)
referenced[mesh.faces] = True
else:
# this is used for geometry without faces
referenced = np.ones(len(mesh.vertices), dtype=np.bool)
# collect vertex attributes into sequence
stacked = [mesh.vertices * (10 ** digits_vertex)]
# UV texture visuals require us to update the
# vertices and normals differently
if (use_tex and