How to use the trimesh.constants.tol function in trimesh

To help you get started, we’ve selected a few trimesh examples, based on popular ways it is used in public projects.

Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.

github mikedh / trimesh / trimesh / proximity.py View on Github external
# 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
github mikedh / trimesh / trimesh / creation.py View on Github external
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
github mikedh / trimesh / trimesh / intersections.py View on Github external
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
github mikedh / trimesh / trimesh / exchange / gltf.py View on Github external
# 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
github mikedh / trimesh / trimesh / base.py View on Github external
    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
github mikedh / trimesh / trimesh / graph.py View on Github external
"""
    # 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
github mikedh / trimesh / trimesh / comparison.py View on Github external
# 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
github mikedh / trimesh / trimesh / exchange / obj.py View on Github external
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
github mikedh / trimesh / trimesh / ray / ray_triangle_cpu.py View on Github external
# 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
github mikedh / trimesh / trimesh / grouping.py View on Github external
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