def test_assert_nonzero_norm_passthrough(self): """Checks that the assert is a passthrough when the flag is False.""" vector_input = _pick_random_vector() vector_output = asserts.assert_nonzero_norm(vector_input) self.assertIs(vector_input, vector_output)
def normal(v0: type_alias.TensorLike, v1: type_alias.TensorLike, v2: type_alias.TensorLike, clockwise: bool = False, normalize: bool = True, name: str = "triangle_normal") -> tf.Tensor: """Computes face normals (triangles). Note: In the following, A1 to An are optional batch dimensions, which must be broadcast compatible. Args: v0: A tensor of shape `[A1, ..., An, 3]`, where the last dimension represents the first vertex of a triangle. v1: A tensor of shape `[A1, ..., An, 3]`, where the last dimension represents the second vertex of a triangle. v2: A tensor of shape `[A1, ..., An, 3]`, where the last dimension represents the third vertex of a triangle. clockwise: Winding order to determine front-facing triangles. normalize: A `bool` indicating whether output normals should be normalized by the function. name: A name for this op. Defaults to "triangle_normal". Returns: A tensor of shape `[A1, ..., An, 3]`, where the last dimension represents a normalized vector. Raises: ValueError: If the shape of `v0`, `v1`, or `v2` is not supported. """ with tf.name_scope(name): v0 = tf.convert_to_tensor(value=v0) v1 = tf.convert_to_tensor(value=v1) v2 = tf.convert_to_tensor(value=v2) shape.check_static(tensor=v0, tensor_name="v0", has_dim_equals=(-1, 3)) shape.check_static(tensor=v1, tensor_name="v1", has_dim_equals=(-1, 3)) shape.check_static(tensor=v2, tensor_name="v2", has_dim_equals=(-1, 3)) shape.compare_batch_dimensions(tensors=(v0, v1, v2), last_axes=-2, broadcast_compatible=True) normal_vector = vector.cross(v1 - v0, v2 - v0, axis=-1) normal_vector = asserts.assert_nonzero_norm(normal_vector) if not clockwise: normal_vector *= -1.0 if normalize: return tf.nn.l2_normalize(normal_vector, axis=-1) return normal_vector
def test_assert_nonzero_norm_exception_raised(self, value, dtype): """Checks that assert_nonzero_norm fails for values below eps.""" vector = tf.constant((value, ), dtype=dtype) with self.assertRaises(tf.errors.InvalidArgumentError): self.evaluate(asserts.assert_nonzero_norm(vector))
def interpolate(points, weights, indices, normalize=True, allow_negative_weights=False, name=None): """Weighted interpolation for M-D point sets. Given an M-D point set, this function can be used to generate a new point set that is formed by interpolating a subset of points in the set. Note: In the following, A1 to An, and B1 to Bk are optional batch dimensions. Args: points: A tensor with shape `[B1, ..., Bk, M] and rank R > 1, where M is the dimensionality of the points. weights: A tensor with shape `[A1, ..., An, P]`, where P is the number of points to interpolate for each output point. indices: A tensor of dtype tf.int32 and shape `[A1, ..., An, P, R-1]`, which contains the point indices to be used for each output point. The R-1 dimensional axis gives the slice index of a single point in `points`. The first n+1 dimensions of weights and indices must match, or be broadcast compatible. normalize: A `bool` describing whether or not to normalize the weights on the last axis. allow_negative_weights: A `bool` describing whether or not negative weights are allowed. name: A name for this op. Defaults to "weighted_interpolate". Returns: A tensor of shape `[A1, ..., An, M]` storing the interpolated M-D points. The first n dimensions will be the same as weights and indices. """ with tf.compat.v1.name_scope(name, "weighted_interpolate", [points, weights, indices]): points = tf.convert_to_tensor(value=points) weights = tf.convert_to_tensor(value=weights) indices = tf.convert_to_tensor(value=indices) shape.check_static(tensor=points, tensor_name="points", has_rank_greater_than=1) shape.check_static(tensor=indices, tensor_name="indices", has_rank_greater_than=1, has_dim_equals=(-1, points.shape.ndims - 1)) shape.compare_dimensions(tensors=(weights, indices), axes=(-1, -2), tensor_names=("weights", "indices")) shape.compare_batch_dimensions(tensors=(weights, indices), last_axes=(-2, -3), tensor_names=("weights", "indices"), broadcast_compatible=True) if not allow_negative_weights: weights = asserts.assert_all_above(weights, 0.0, open_bound=False) if normalize: sums = tf.reduce_sum(input_tensor=weights, axis=-1, keepdims=True) sums = asserts.assert_nonzero_norm(sums) weights = safe_ops.safe_signed_div(weights, sums) point_lists = tf.gather_nd(points, indices) return vector.dot(point_lists, tf.expand_dims(weights, axis=-1), axis=-2, keepdims=False)