diff --git a/latest/.doctrees/environment.pickle b/latest/.doctrees/environment.pickle index ea3d5f24e88..f89ad4a71b3 100644 Binary files a/latest/.doctrees/environment.pickle and b/latest/.doctrees/environment.pickle differ diff --git a/latest/.doctrees/index.doctree b/latest/.doctrees/index.doctree index 497fc405322..0beb74c9abd 100644 Binary files a/latest/.doctrees/index.doctree and b/latest/.doctrees/index.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.KDTree.build.doctree b/latest/.doctrees/reference/generated/compas.geometry.KDTree.build.doctree index cccf20e180c..89a5d7e4592 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.KDTree.build.doctree and b/latest/.doctrees/reference/generated/compas.geometry.KDTree.build.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.KDTree.doctree b/latest/.doctrees/reference/generated/compas.geometry.KDTree.doctree index 2c95c6d0461..3a499e768f6 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.KDTree.doctree and b/latest/.doctrees/reference/generated/compas.geometry.KDTree.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.KDTree.nearest_neighbor.doctree b/latest/.doctrees/reference/generated/compas.geometry.KDTree.nearest_neighbor.doctree index 59e8ae96bc9..0511443793f 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.KDTree.nearest_neighbor.doctree and b/latest/.doctrees/reference/generated/compas.geometry.KDTree.nearest_neighbor.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.KDTree.nearest_neighbors.doctree b/latest/.doctrees/reference/generated/compas.geometry.KDTree.nearest_neighbors.doctree index 9a68ee4b8fa..202494fdcdb 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.KDTree.nearest_neighbors.doctree and b/latest/.doctrees/reference/generated/compas.geometry.KDTree.nearest_neighbors.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.barycentric_coordinates.doctree b/latest/.doctrees/reference/generated/compas.geometry.barycentric_coordinates.doctree index 1fa97db2769..179ad270789 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.barycentric_coordinates.doctree and b/latest/.doctrees/reference/generated/compas.geometry.barycentric_coordinates.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.conforming_delaunay_triangulation.doctree b/latest/.doctrees/reference/generated/compas.geometry.conforming_delaunay_triangulation.doctree index 5d804674ef9..9263ed6d94e 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.conforming_delaunay_triangulation.doctree and b/latest/.doctrees/reference/generated/compas.geometry.conforming_delaunay_triangulation.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.constrained_delaunay_triangulation.doctree b/latest/.doctrees/reference/generated/compas.geometry.constrained_delaunay_triangulation.doctree index 305a7c1a68a..49722265524 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.constrained_delaunay_triangulation.doctree and b/latest/.doctrees/reference/generated/compas.geometry.constrained_delaunay_triangulation.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.delaunay_from_points.doctree b/latest/.doctrees/reference/generated/compas.geometry.delaunay_from_points.doctree index 8d8a550a182..c32c2e09f08 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.delaunay_from_points.doctree and b/latest/.doctrees/reference/generated/compas.geometry.delaunay_from_points.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.delaunay_from_points_numpy.doctree b/latest/.doctrees/reference/generated/compas.geometry.delaunay_from_points_numpy.doctree index ae1bfce7b8a..349b40b5b2d 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.delaunay_from_points_numpy.doctree and b/latest/.doctrees/reference/generated/compas.geometry.delaunay_from_points_numpy.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.delaunay_triangulation.doctree b/latest/.doctrees/reference/generated/compas.geometry.delaunay_triangulation.doctree index 72d2356d56d..a9ed61eb460 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.delaunay_triangulation.doctree and b/latest/.doctrees/reference/generated/compas.geometry.delaunay_triangulation.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.discrete_coons_patch.doctree b/latest/.doctrees/reference/generated/compas.geometry.discrete_coons_patch.doctree index cd42a9b88e9..edaa5f2328a 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.discrete_coons_patch.doctree and b/latest/.doctrees/reference/generated/compas.geometry.discrete_coons_patch.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.earclip_polygon.doctree b/latest/.doctrees/reference/generated/compas.geometry.earclip_polygon.doctree index 82efc063ba2..4b7d1e36757 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.earclip_polygon.doctree and b/latest/.doctrees/reference/generated/compas.geometry.earclip_polygon.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.tween_points.doctree b/latest/.doctrees/reference/generated/compas.geometry.tween_points.doctree index 86b44b219bb..9d96e81c57b 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.tween_points.doctree and b/latest/.doctrees/reference/generated/compas.geometry.tween_points.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.tween_points_distance.doctree b/latest/.doctrees/reference/generated/compas.geometry.tween_points_distance.doctree index 885ff1c3171..87cbe51a50d 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.tween_points_distance.doctree and b/latest/.doctrees/reference/generated/compas.geometry.tween_points_distance.doctree differ diff --git a/latest/.doctrees/reference/generated/compas.geometry.voronoi_from_points_numpy.doctree b/latest/.doctrees/reference/generated/compas.geometry.voronoi_from_points_numpy.doctree index acebbfa74e1..28d76a9daac 100644 Binary files a/latest/.doctrees/reference/generated/compas.geometry.voronoi_from_points_numpy.doctree and b/latest/.doctrees/reference/generated/compas.geometry.voronoi_from_points_numpy.doctree differ diff --git a/latest/_modules/compas/geometry/interpolation_barycentric.html b/latest/_modules/compas/geometry/interpolation_barycentric.html new file mode 100644 index 00000000000..7c737468ec2 --- /dev/null +++ b/latest/_modules/compas/geometry/interpolation_barycentric.html @@ -0,0 +1,585 @@ + + + + + + + + + + + compas.geometry.interpolation_barycentric — compas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + +
+
This is the WIP documentation for the pre-release of COMPAS 2.0. The documentation of COMPAS 1.x is available here.
+
+ + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for compas.geometry.interpolation_barycentric

+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import division
+
+from compas.geometry import subtract_vectors
+from compas.geometry import dot_vectors
+
+
+
[docs]def barycentric_coordinates(point, triangle): + """Compute the barycentric coordinates of a point wrt to a triangle. + + Parameters + ---------- + point: [float, float, float] | :class:`compas.geometry.Point` + Point location. + triangle: [point, point, point] + A triangle defined by 3 points. + + Returns + ------- + [float, float, float] + The barycentric coordinates of the point. + + """ + a, b, c = triangle + v0 = subtract_vectors(b, a) + v1 = subtract_vectors(c, a) + v2 = subtract_vectors(point, a) + d00 = dot_vectors(v0, v0) + d01 = dot_vectors(v0, v1) + d11 = dot_vectors(v1, v1) + d20 = dot_vectors(v2, v0) + d21 = dot_vectors(v2, v1) + D = d00 * d11 - d01 * d01 + v = (d11 * d20 - d01 * d21) / D + w = (d00 * d21 - d01 * d20) / D + u = 1.0 - v - w + return [u, v, w]
+
+ +
+ + + +
+ +
+ +
+
+
+ +
+ +
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/latest/_modules/compas/geometry/interpolation_coons.html b/latest/_modules/compas/geometry/interpolation_coons.html new file mode 100644 index 00000000000..d11f4e3e73c --- /dev/null +++ b/latest/_modules/compas/geometry/interpolation_coons.html @@ -0,0 +1,650 @@ + + + + + + + + + + + compas.geometry.interpolation_coons — compas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + +
+
This is the WIP documentation for the pre-release of COMPAS 2.0. The documentation of COMPAS 1.x is available here.
+
+ + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for compas.geometry.interpolation_coons

+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import division
+
+from compas.geometry import add_vectors
+from compas.geometry import scale_vector
+from compas.geometry import subtract_vectors
+from compas.geometry import sum_vectors
+
+from compas.utilities import normalize_values
+
+
+
[docs]def discrete_coons_patch(ab, bc, dc, ad): + """Creates a coons patch from a set of four or three boundary + polylines (ab, bc, dc, ad). + + Parameters + ---------- + ab : list[[float, float, float] | :class:`compas.geometry.Point`] + The XYZ coordinates of the vertices of the first polyline. + bc : list[[float, float, float] | :class:`compas.geometry.Point`] + The XYZ coordinates of the vertices of the second polyline. + dc : list[[float, float, float] | :class:`compas.geometry.Point`] + The XYZ coordinates of the vertices of the third polyline. + ad : list[[float, float, float] | :class:`compas.geometry.Point`] + The XYZ coordinates of the vertices of the fourth polyline. + + Returns + ------- + list[[float, float, float]] + The points of the coons patch. + list[list[int]] + List of faces, with every face a list of indices into the point list. + + Notes + ----- + The vertices of the polylines are assumed to be in the following order:: + + b -----> c + ^ ^ + | | + | | + a -----> d + + To create a triangular patch, one of the input polylines should be None. + (Warning! This will result in duplicate vertices.) + + For more information see [1]_ and [2]_. + + References + ---------- + .. [1] Wikipedia. *Coons patch*. + Available at: https://en.wikipedia.org/wiki/Coons_patch. + .. [2] Robert Ferreol. *Patch de Coons*. + Available at: https://www.mathcurve.com/surfaces/patchcoons/patchcoons.shtml + + Examples + -------- + >>> + + """ + if not ab: + ab = [ad[0]] * len(dc) + if not bc: + bc = [ab[-1]] * len(ad) + if not dc: + dc = [bc[-1]] * len(ab) + if not ad: + ad = [dc[0]] * len(bc) + + n = len(ab) + m = len(bc) + + n_norm = normalize_values(range(n)) + m_norm = normalize_values(range(m)) + + array = [[0] * m for i in range(n)] + for i, ki in enumerate(n_norm): + for j, kj in enumerate(m_norm): + # first function: linear interpolation of first two opposite curves + lin_interp_ab_dc = add_vectors(scale_vector(ab[i], (1 - kj)), scale_vector(dc[i], kj)) + # second function: linear interpolation of other two opposite curves + lin_interp_bc_ad = add_vectors(scale_vector(ad[j], (1 - ki)), scale_vector(bc[j], ki)) + # third function: linear interpolation of four corners resulting a hypar + a = scale_vector(ab[0], (1 - ki) * (1 - kj)) + b = scale_vector(bc[0], ki * (1 - kj)) + c = scale_vector(dc[-1], ki * kj) + d = scale_vector(ad[-1], (1 - ki) * kj) + lin_interp_a_b_c_d = sum_vectors([a, b, c, d]) + # coons patch = first + second - third functions + array[i][j] = subtract_vectors(add_vectors(lin_interp_ab_dc, lin_interp_bc_ad), lin_interp_a_b_c_d) # type: ignore + + # create vertex list + vertices = [] + for i in range(n): + vertices += array[i] + + # create face vertex list + faces = [] + for i in range(n - 1): + for j in range(m - 1): + faces.append([i * m + j, i * m + j + 1, (i + 1) * m + j + 1, (i + 1) * m + j]) + return vertices, faces
+
+ +
+ + + +
+ +
+ +
+
+
+ +
+ +
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/latest/_modules/compas/geometry/interpolation_tweening.html b/latest/_modules/compas/geometry/interpolation_tweening.html new file mode 100644 index 00000000000..86405af036b --- /dev/null +++ b/latest/_modules/compas/geometry/interpolation_tweening.html @@ -0,0 +1,634 @@ + + + + + + + + + + + compas.geometry.interpolation_tweening — compas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + +
+
This is the WIP documentation for the pre-release of COMPAS 2.0. The documentation of COMPAS 1.x is available here.
+
+ + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for compas.geometry.interpolation_tweening

+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import division
+
+from compas.geometry import add_vectors
+from compas.geometry import subtract_vectors
+from compas.geometry import scale_vector
+from compas.geometry import distance_point_point
+
+
+
[docs]def tween_points(points1, points2, num): + """Compute the interpolated points between two sets of points. + + Parameters + ---------- + points1 : list[[float, float, float] | :class:`compas.geometry.Point`] + The first set of points. + points2 : list[[float, float, float] | :class:`compas.geometry.Point`] + The second set of points. + num : int + The number of interpolated sets to return. + + Returns + ------- + list[list[[float, float, float]]] + Nested list of points. + + Raises + ------ + AssertionError + When the two point sets do not have the same length. + + Notes + ----- + The two point sets should have the same length. + + Examples + -------- + >>> + + """ + vectors = [subtract_vectors(p2, p1) for p1, p2 in zip(points1, points2)] + tweens = [] + for j in range(num): + tween = [] + for point, vector in zip(points1, vectors): + scale = (j + 1.0) / (num + 1.0) + tween.append(add_vectors(point, scale_vector(vector, scale))) + tweens.append(tween) + return tweens
+ + +
[docs]def tween_points_distance(points1, points2, dist, index=None): + """Compute an interpolated set of points between two sets of points, at + a given distance. + + Parameters + ---------- + points1 : list[[float, float, float] | :class:`compas.geometry.Point`] + The first set of points. + points2 : list[[float, float, float] | :class:`compas.geometry.Point`] + The second set of points. + dist : float + The distance from the first set to the second at which to compute the interpolated set. + index: int, optional + The index of the point in the first set from which to calculate the distance to the second set. + If no value is given, the first point will be used. + + Returns + ------- + list[list[[float, float, float]]] + List of points. + + """ + if not index: + index = 0 + d = distance_point_point(points1[index], points2[index]) + scale = float(dist) / d + tweens = [] + for i in range(len(points1)): + tweens.append( + add_vectors( + points1[i], + scale_vector(subtract_vectors(points2[i], points1[i]), scale), + ) + ) + return tweens
+
+ +
+ + + +
+ +
+ +
+
+
+ +
+ +
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/latest/_modules/compas/geometry/kdtree.html b/latest/_modules/compas/geometry/kdtree.html new file mode 100644 index 00000000000..08c138351be --- /dev/null +++ b/latest/_modules/compas/geometry/kdtree.html @@ -0,0 +1,701 @@ + + + + + + + + + + + compas.geometry.kdtree — compas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + +
+
This is the WIP documentation for the pre-release of COMPAS 2.0. The documentation of COMPAS 1.x is available here.
+
+ + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for compas.geometry.kdtree

+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import division
+
+import collections
+
+from ._core.distance import distance_point_point_sqrd
+
+
+Node = collections.namedtuple("Node", "point axis label left right")
+
+
+
[docs]class KDTree(object): + """A tree for nearest neighbor search in a k-dimensional space. + + Parameters + ---------- + objects : sequence[[float, float, float] | :class:`compas.geometry.Point`], optional + A list of objects to populate the tree with. + If objects are provided, the tree is built automatically. + Otherwise, use :meth:`build`. + + Attributes + ---------- + root : Node + The root node of the built tree. + This is the median with respect to the different dimensions of the tree. + + Notes + ----- + For more info, see [1]_ and [2]_. + + References + ---------- + .. [1] Wikipedia. *k-d tree*. + Available at: https://en.wikipedia.org/wiki/K-d_tree. + .. [2] Dell'Amico, M. *KD-Tree for nearest neighbor search in a K-dimensional space (Python recipe)*. + Available at: http://code.activestate.com/recipes/577497-kd-tree-for-nearest-neighbor-search-in-a-k-dimensional-space/. + + Examples + -------- + >>> + + """ + + def __init__(self, objects=None): + self.root = None + if objects: + self.root = self.build([(o, i) for i, o in enumerate(objects)]) + +
[docs] def build(self, objects, axis=0): + """Populate a kd-tree with given objects. + + Parameters + ---------- + objects : sequence[tuple[[float, float, float] | :class:`compas.geometry.Point`, int or str]] + The tree objects as a sequence of point-label tuples. + axis : int, optional + The axis along which to build. + + Returns + ------- + Node or None + The root node, or None if the sequence of objects is empty. + + """ + if not objects: + return + + objects.sort(key=lambda o: o[0][axis]) + median_idx = len(objects) // 2 + median_point, median_label = objects[median_idx] + next_axis = (axis + 1) % 3 + + return Node( + median_point, + axis, + median_label, + self.build(objects[:median_idx], next_axis), + self.build(objects[median_idx + 1 :], next_axis), + )
+ +
[docs] def nearest_neighbor(self, point, exclude=None): + """Find the nearest neighbor to a given point, + excluding neighbors that have already been found. + + Parameters + ---------- + point : [float, float, float] | :class:`compas.geometry.Point` + XYZ coordinates of the base point. + exclude : sequence[int or str], optional + A sequence of point identified by their label to exclude from the search. + + Returns + ------- + [[float, float, float], int or str, float] + XYZ coordinates of the nearest neighbor. + Label of the nearest neighbor. + Distance to the base point. + + """ + + def search(node): + if node is None: + return + + d2 = distance_point_point_sqrd(point, node.point) + if d2 < best[2]: + if node.label not in exclude: + best[:] = node.point, node.label, d2 + + d = point[node.axis] - node.point[node.axis] + if d <= 0: + close, far = node.left, node.right + else: + close, far = node.right, node.left + + search(close) + if d**2 < best[2]: + search(far) + + exclude = set(exclude or []) + best = [None, None, float("inf")] + search(self.root) + best[2] **= 0.5 + return best
+ +
[docs] def nearest_neighbors(self, point, number, distance_sort=False): + """Find the N nearest neighbors to a given point. + + Parameters + ---------- + point : [float, float, float] | :class:`compas.geometry.Point` + XYZ coordinates of the base point. + number : int + The number of nearest neighbors. + distance_sort : bool, optional + Sort the nearest neighbors by distance to the base point. + + Returns + ------- + list[[[float, float, float], int or str, float]] + A list of N nearest neighbors. + + """ + nnbrs = [] + exclude = set() + for i in range(number): + nnbr = self.nearest_neighbor(point, exclude) + nnbrs.append(nnbr) + exclude.add(nnbr[1]) + if distance_sort: + return sorted(nnbrs, key=lambda nnbr: nnbr[2]) + return nnbrs
+
+ +
+ + + +
+ +
+ +
+
+
+ +
+ +
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/latest/_modules/compas/geometry/triangulation_delaunay.html b/latest/_modules/compas/geometry/triangulation_delaunay.html new file mode 100644 index 00000000000..283fe3859bf --- /dev/null +++ b/latest/_modules/compas/geometry/triangulation_delaunay.html @@ -0,0 +1,639 @@ + + + + + + + + + + + compas.geometry.triangulation_delaunay — compas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + +
+
This is the WIP documentation for the pre-release of COMPAS 2.0. The documentation of COMPAS 1.x is available here.
+
+ + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for compas.geometry.triangulation_delaunay

+from __future__ import absolute_import
+from __future__ import division
+from __future__ import print_function
+
+from compas.plugins import pluggable
+
+
+
[docs]@pluggable(category="triangulation") +def delaunay_triangulation(points): + """Construct a Delaunay triangulation of set of vertices. + + Parameters + ---------- + points : list + XY(Z) coordinates of the points to triangulate. + + Returns + ------- + (list, list) + The vertices of the triangulation, and the faces of the triangulation. + + Examples + -------- + >>> + + """ + raise NotImplementedError
+ + +
[docs]@pluggable(category="triangulation") +def constrained_delaunay_triangulation(boundary, polylines=None, polygons=None): + """Construct a Delaunay triangulation of set of vertices, constrained to the specified segments. + + Parameters + ---------- + boundary : list + Ordered points on the boundary. + polylines : list, optional + Lists of ordered points defining internal guide curves. + polygons : list, optional + Lists of ordered points defining holes in the triangulation. + + Returns + ------- + (list, list) + The vertices of the triangulation, and the faces of the triangulation. + + Notes + ----- + No additional points will be inserted in the triangulation. + + Examples + -------- + >>> + + """ + pass
+ + +
[docs]@pluggable(category="triangulation") +def conforming_delaunay_triangulation(boundary, polylines=None, polygons=None, angle=None, area=None): + """Construct a Conforming Delaunay triangulation of set of vertices, constrained to the specified segments. + + Parameters + ---------- + boundary : list + Ordered points on the boundary. + polylines : list, optional + Lists of ordered points defining internal guide curves. + polygons : list, optional + Lists of ordered points defining holes in the triangulation. + angle : float, optional + Minimum angle constraint for the triangles of the triangulation. + If an angle constraint is given, "Steiner points" may be inserted internally + and along the constraint segments to satisfy the constraint. + The angle constraint should be specified in degrees. + area : float, optional + Maximum area constraint for the triangles of the triangulation. + If an area constraint is given, "Steiner points" may be inserted internally + and along the constraint segments to satisfy the constraint. + + Returns + ------- + (list, list) + The vertices of the triangulation, and the faces of the triangulation. + + Examples + -------- + >>> + + """ + raise NotImplementedError
+
+ +
+ + + +
+ +
+ +
+
+
+ +
+ +
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/latest/_modules/compas/geometry/triangulation_delaunay_none.html b/latest/_modules/compas/geometry/triangulation_delaunay_none.html new file mode 100644 index 00000000000..f63959ae4ea --- /dev/null +++ b/latest/_modules/compas/geometry/triangulation_delaunay_none.html @@ -0,0 +1,767 @@ + + + + + + + + + + + compas.geometry.triangulation_delaunay_none — compas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + +
+
This is the WIP documentation for the pre-release of COMPAS 2.0. The documentation of COMPAS 1.x is available here.
+
+ + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for compas.geometry.triangulation_delaunay_none

+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import division
+
+import random
+
+from compas.geometry import centroid_points
+from compas.geometry import distance_point_point
+from compas.geometry import add_vectors
+from compas.geometry import bounding_box
+
+from compas.geometry import is_point_in_polygon_xy
+from compas.geometry import is_point_in_triangle_xy
+from compas.geometry import is_point_in_circle_xy
+
+from compas.geometry import circle_from_points_xy
+
+
+
[docs]def delaunay_from_points(points, boundary=None, holes=None, tiny=1e-12): + """Computes the delaunay triangulation for a list of points. + + Parameters + ---------- + points : sequence[[float, float, float] | :class:`compas.geometry.Point`] + XYZ coordinates of the original points. + boundary : sequence[[float, float, float] | :class:`compas.geometry.Point`] | :class:`compas.geometry.Polygon`, optional + List of ordered points describing the outer boundary. + holes : sequence[sequence[[float, float, float] | :class:`compas.geometry.Point`] | :class:`compas.geometry.Polygon`], optional + List of polygons (ordered points describing internal holes. + + Returns + ------- + list[[int, int, int]] + The faces of the triangulation. + Each face is a triplet of indices referring to the list of point coordinates. + + Notes + ----- + For more info, see [1]_. + + References + ---------- + .. [1] Sloan, S. W., 1987 *A fast algorithm for constructing Delaunay triangulations in the plane* + Advances in Engineering Software 9(1): 34-55, 1978. + + Examples + -------- + >>> + + """ + from compas.datastructures import Mesh + from compas.datastructures import trimesh_swap_edge + + def super_triangle(coords, ccw=True): + centpt = centroid_points(coords) + bbpts = bounding_box(coords) + dis = distance_point_point(bbpts[0], bbpts[2]) + dis = dis * 300 + v1 = (0 * dis, 2 * dis, 0) + v2 = (1.73205 * dis, -1.0000000000001 * dis, 0) # due to numerical issues + v3 = (-1.73205 * dis, -1 * dis, 0) + pt1 = add_vectors(centpt, v1) + pt2 = add_vectors(centpt, v2) + pt3 = add_vectors(centpt, v3) + if ccw: + return pt1, pt3, pt2 + return pt1, pt2, pt3 + + mesh = Mesh() + + # to avoid numerical issues for perfectly structured point sets + points = [ + ( + point[0] + random.uniform(-tiny, tiny), + point[1] + random.uniform(-tiny, tiny), + 0.0, + ) + for point in points + ] + + # create super triangle + pt1, pt2, pt3 = super_triangle(points) + + # add super triangle vertices to mesh + n = len(points) + super_keys = n, n + 1, n + 2 + + mesh.add_vertex(super_keys[0], {"x": pt1[0], "y": pt1[1], "z": pt1[2]}) + mesh.add_vertex(super_keys[1], {"x": pt2[0], "y": pt2[1], "z": pt2[2]}) + mesh.add_vertex(super_keys[2], {"x": pt3[0], "y": pt3[1], "z": pt3[2]}) + + mesh.add_face(super_keys) + + # iterate over points + for key, point in enumerate(points): + # newtris should be intialised here + + # check in which triangle this point falls + for fkey in list(mesh.faces()): + abc = mesh.face_coordinates(fkey) + + if is_point_in_triangle_xy(point, abc, True): + # generate 3 new triangles (faces) and delete surrounding triangle + key, newtris = mesh.insert_vertex(fkey, key=key, xyz=point, return_fkeys=True) + break + + while newtris: + fkey = newtris.pop() + + face = mesh.face_vertices(fkey) + i = face.index(key) + u = face[i - 2] + v = face[i - 1] + + nbr = mesh.halfedge[v][u] + + if nbr is not None: + a, b, c = mesh.face_coordinates(nbr) + circle = circle_from_points_xy(a, b, c) + + if is_point_in_circle_xy(point, circle): + fkey, nbr = trimesh_swap_edge(mesh, (u, v)) + newtris.append(fkey) + newtris.append(nbr) + + # Delete faces adjacent to supertriangle + for key in super_keys: + mesh.delete_vertex(key) + + # Delete faces outside of boundary + if boundary: + for fkey in list(mesh.faces()): + centroid = mesh.face_centroid(fkey) + if not is_point_in_polygon_xy(centroid, boundary): + mesh.delete_face(fkey) + + # Delete faces inside of inside boundaries + if holes: + for polygon in holes: + for fkey in list(mesh.faces()): + centroid = mesh.face_centroid(fkey) + if is_point_in_polygon_xy(centroid, polygon): + mesh.delete_face(fkey) + + return [mesh.face_vertices(fkey) for fkey in mesh.faces()]
+ + +# def voronoi_from_delaunay(delaunay): +# """Construct the Voronoi dual of the triangulation of a set of points. + +# Parameters +# ---------- +# delaunay : Mesh +# A delaunay mesh. + +# Returns +# ------- +# Mesh +# The corresponding voronoi mesh. + +# Warnings +# -------- +# This function does not work properly if all vertices of the delaunay +# are on the boundary. + +# Examples +# -------- +# .. plot:: +# :include-source: + +# from compas.datastructures import Mesh +# from compas.datastructures import trimesh_remesh +# from compas.geometry import delaunay_from_points +# from compas.geometry import voronoi_from_delaunay +# from compas.geometry import pointcloud_xy +# from compas_plotters import MeshPlotter + +# points = pointcloud_xy(10, (0, 10)) +# faces = delaunay_from_points(points) +# delaunay = Mesh.from_vertices_and_faces(points, faces) + +# trimesh_remesh(delaunay, 1.0, allow_boundary_split=True) + +# points = [delaunay.vertex_coordinates(key) for key in delaunay.vertices()] +# faces = delaunay_from_points(points) +# delaunay = Mesh.from_vertices_and_faces(points, faces) + +# voronoi = voronoi_from_delaunay(delaunay) + +# lines = [] +# for u, v in voronoi.edges(): +# lines.append({ +# 'start': voronoi.vertex_coordinates(u, 'xy'), +# 'end' : voronoi.vertex_coordinates(v, 'xy'), +# 'width': 1.0 +# }) + +# plotter = MeshPlotter(delaunay) + +# plotter.draw_lines(lines) + +# plotter.draw_vertices( +# radius=0.075, +# facecolor={key: '#0092d2' for key in delaunay.vertices() if key not in delaunay.vertices_on_boundary()}) + +# plotter.draw_edges(color='#cccccc') + +# plotter.show() + +# """ +# voronoi = mesh_dual(delaunay) + +# for key in voronoi.vertices(): +# a, b, c = delaunay.face_coordinates(key) +# center, radius, normal = circle_from_points_xy(a, b, c) +# voronoi.vertex[key]['x'] = center[0] +# voronoi.vertex[key]['y'] = center[1] +# voronoi.vertex[key]['z'] = center[2] + +# return voronoi +
+ +
+ + + +
+ +
+ +
+
+
+ +
+ +
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/latest/_modules/compas/geometry/triangulation_delaunay_numpy.html b/latest/_modules/compas/geometry/triangulation_delaunay_numpy.html new file mode 100644 index 00000000000..d7c88f1110c --- /dev/null +++ b/latest/_modules/compas/geometry/triangulation_delaunay_numpy.html @@ -0,0 +1,599 @@ + + + + + + + + + + + compas.geometry.triangulation_delaunay_numpy — compas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + +
+
This is the WIP documentation for the pre-release of COMPAS 2.0. The documentation of COMPAS 1.x is available here.
+
+ + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for compas.geometry.triangulation_delaunay_numpy

+from __future__ import print_function
+from __future__ import absolute_import
+from __future__ import division
+
+from numpy import asarray
+from scipy.spatial import Voronoi
+from scipy.spatial import Delaunay
+
+
+
[docs]def delaunay_from_points_numpy(points): + """Computes the delaunay triangulation for a list of points using Numpy. + + Parameters + ---------- + points : sequence[[float, float, float] | :class:`compas.geometry.Point`] + XYZ coordinates of the original points. + + Returns + ------- + list[[int, int, int]] + The faces of the triangulation. + Each face is a triplet of indices referring to the list of point coordinates. + + Examples + -------- + >>> + + """ + xyz = asarray(points) + d = Delaunay(xyz[:, 0:2]) + return d.simplices
+ + +
[docs]def voronoi_from_points_numpy(points): + """Generate a voronoi diagram from a set of points. + + Parameters + ---------- + points : sequence[[float, float, float] | :class:`compas.geometry.Point`] + XYZ coordinates of the voronoi sites. + + Returns + ------- + + Examples + -------- + >>> + + """ + points = asarray(points) + voronoi = Voronoi(points) + return voronoi
+
+ +
+ + + +
+ +
+ +
+
+
+ +
+ +
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/latest/_modules/compas/geometry/triangulation_earclip.html b/latest/_modules/compas/geometry/triangulation_earclip.html new file mode 100644 index 00000000000..0787b3dd411 --- /dev/null +++ b/latest/_modules/compas/geometry/triangulation_earclip.html @@ -0,0 +1,611 @@ + + + + + + + + + + + compas.geometry.triangulation_earclip — compas + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+ + +
+
This is the WIP documentation for the pre-release of COMPAS 2.0. The documentation of COMPAS 1.x is available here.
+
+ + + + +
+
+ +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ +
+ +
+ + + + +
+ +
+ + +
+
+ + + + + +
+ +

Source code for compas.geometry.triangulation_earclip

+from compas.geometry import is_ccw_xy, is_point_in_triangle_xy
+
+
+
[docs]def earclip_polygon(polygon): + """Triangulate a polygon using the ear clipping method. + + Parameters + ---------- + polygon : :class:`compas.geometry.Polygon` | list[:class:`compas.geometry.Point`] + A polygon defined by a sequence of points. + + Returns + ------- + list[[point, point, point]] + A list of triangles. + + Raises + ------ + Exception + If not all points were consumed by the procedure. + + """ + + def find_ear(points, point_index): + p = len(points) + if p == 3: + triangle = [ + point_index[id(points[0])], + point_index[id(points[1])], + point_index[id(points[2])], + ] + del points[2] + del points[1] + del points[0] + return triangle + for i in range(-2, p - 2): + a = points[i] + b = points[i + 1] + c = points[i + 2] + is_valid = True + if not is_ccw_xy(b, c, a): + continue + for j in range(p): + if j == i or j == i + 1 or j == i + 2: + continue + if is_point_in_triangle_xy(points[j], (a, b, c)): + is_valid = False + break + if is_valid: + del points[i + 1] + return [point_index[id(a)], point_index[id(b)], point_index[id(c)]] + + points = list(polygon) + point_index = {id(point): index for index, point in enumerate(points)} + + triangles = [] + while len(points) >= 3: + ear = find_ear(points, point_index) + triangles.append(ear) + + if points: + raise Exception("Not all points were consumed by the clipping procedure.") + + return triangles
+
+ +
+ + + +
+ +
+ +
+
+
+ +
+ +
+ +
+ + + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/latest/_modules/index.html b/latest/_modules/index.html index 071f9ec77fa..ecaace7a823 100644 --- a/latest/_modules/index.html +++ b/latest/_modules/index.html @@ -550,7 +550,6 @@

All modules for which code is available

  • compas.geometry._core.centroids
  • compas.geometry._core.constructors
  • compas.geometry._core.distance
  • -
  • compas.geometry._core.kdtree
  • compas.geometry._core.matrices
  • compas.geometry._core.normals
  • compas.geometry._core.nurbs
  • @@ -588,12 +587,13 @@

    All modules for which code is available

  • compas.geometry.hull
  • compas.geometry.hull_numpy
  • compas.geometry.icp_numpy
  • -
  • compas.geometry.interpolation.barycentric
  • -
  • compas.geometry.interpolation.coons
  • -
  • compas.geometry.interpolation.tweening
  • +
  • compas.geometry.interpolation_barycentric
  • +
  • compas.geometry.interpolation_coons
  • +
  • compas.geometry.interpolation_tweening
  • compas.geometry.intersections
  • compas.geometry.offset
  • +
  • compas.geometry.kdtree
  • +
  • compas.geometry.offset
  • compas.geometry.plane
  • compas.geometry.point
  • compas.geometry.pointcloud
  • @@ -622,11 +622,11 @@

    All modules for which code is available

  • compas.geometry.surfaces.toroidal
  • compas.geometry.transformation
  • compas.geometry.translation
  • -
  • compas.geometry.triangulation
  • -
  • compas.geometry.trimesh_curvature
  • +
  • compas.geometry.triangulation_delaunay
  • +
  • compas.geometry.triangulation_delaunay_none
  • +
  • compas.geometry.triangulation_delaunay_numpy
  • +
  • compas.geometry.triangulation_earclip
  • +
  • compas.geometry.trimesh_curvature
  • compas.geometry.trimesh_descent_numpy
  • compas.geometry.trimesh_geodistance
  • compas.geometry.trimesh_gradient_numpy
  • diff --git a/latest/devguide/code.html b/latest/devguide/code.html index af693584645..96fa207a1a9 100644 --- a/latest/devguide/code.html +++ b/latest/devguide/code.html @@ -168,6 +168,13 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +