Esempio n. 1
0
	def singularity_polyedge_decomposition(self):
		"""Returns a quad patch decomposition of the mesh based on the singularity polyedges, including boundaries and additionnal splits on the boundaries.

		Returns
		-------
		list
			The polyedges forming the decomposition.

		"""
		if self.data['attributes']['polyedges'] == {}:
			self.collect_polyedges()

		polyedges = [polyedge for key, polyedge in self.polyedges(data=True) if (self.is_vertex_singular(polyedge[0]) or self.is_vertex_singular(polyedge[-1])) and not self.is_edge_on_boundary(polyedge[0], polyedge[1])]									

		# split boundaries
		all_splits = [vkey for polyedge in polyedges for vkey in polyedge]
		for boundary in self.boundaries():
			splits = [vkey for vkey in boundary if vkey in all_splits]
			new_splits = []

			if len(splits) == 0:
				new_splits += [vkey for vkey in list(itemgetter(0, int(floor(len(boundary) / 3)), int(floor(len(boundary) * 2 / 3)))(boundary))]
				
			elif len(splits) == 1:
				i = boundary.index(splits[0])
				new_splits += list(itemgetter(i - int(floor(len(boundary) * 2 / 3)), i - int(floor(len(boundary) / 3)))(boundary))
			
			elif len(splits) == 2:			
				one, two = list_split(boundary + boundary[:1], [boundary.index(vkey) for vkey in splits])
				half = one if len(one) > len(two) else two
				new_splits.append(half[int(floor(len(half) / 2))])	

			for vkey in new_splits:
				for nbr in self.vertex_neighbors(vkey):
					if not self.is_edge_on_boundary(vkey, nbr):
						new_polyedge = self.collect_polyedge(vkey, nbr)
						polyedges.append(new_polyedge)
						all_splits = list(set(all_splits + new_polyedge))
						break

		# add boundaries
		polyedges += [polyedge for key, polyedge in self.polyedges(data=True) if self.is_edge_on_boundary(polyedge[0], polyedge[1])]

		# get intersections between polyedges for split
		vertices = [vkey for polyedge in polyedges for vkey in set(polyedge)]
		split_vertices = [vkey for vkey in self.vertices() if vertices.count(vkey) > 1]
		
		# split singularity polyedges
		return [split_polyedge for polyedge in polyedges for split_polyedge in list_split(polyedge, [polyedge.index(vkey) for vkey in split_vertices if vkey in polyedge])]
Esempio n. 2
0
    def singularity_polyedges(self):
        """Collect the polyedges connected to singularities.

        Returns
        -------
        list
            The polyedges connected to singularities.

        """

        poles = set(self.poles())
        # keep only polyedges connected to singularities or along the boundary
        polyedges = [
            polyedge for key, polyedge in self.polyedges(data=True)
            if (self.is_vertex_singular(polyedge[0])
                and not self.is_pole(polyedge[0])) or (self.is_vertex_singular(
                    polyedge[-1]) and not self.is_pole(polyedge[-1]))
            or self.is_edge_on_boundary(polyedge[0], polyedge[1])
        ]

        # get intersections between polyedges for split
        vertices = [vkey for polyedge in polyedges for vkey in set(polyedge)]
        split_vertices = [
            vkey for vkey in self.vertices() if vertices.count(vkey) > 1
        ]

        # split singularity polyedges
        return [
            split_polyedge for polyedge in polyedges
            for split_polyedge in list_split(polyedge, [
                polyedge.index(vkey)
                for vkey in split_vertices if vkey in polyedge
            ])
        ]
Esempio n. 3
0
    def branches_splitting_collapsed_boundaries(self):
        """Add new branches to fix the problem of boundaries with less than three splits that would be collapsed in the decomposition mesh.

		Returns
		-------
		new_branches : list
			List of polylines as list of point XYZ-coordinates.

		"""

        new_branches = []

        all_splits = set(
            list(self.corner_vertices()) + list(self.split_vertices()))

        for polyedge in [bdry + bdry[0:] for bdry in self.boundaries()]:

            splits = set([vkey for vkey in polyedge if vkey in all_splits])
            new_splits = []

            if len(splits) == 0:
                new_splits += [
                    vkey for vkey in list(
                        itemgetter(0, int(floor(len(polyedge) / 3)),
                                   int(floor(len(polyedge) * 2 /
                                             3)))(polyedge))
                ]

            elif len(splits) == 1:
                i = polyedge.index(splits[0])
                new_splits += list(
                    itemgetter(i - int(floor(len(polyedge) * 2 / 3)),
                               i - int(floor(len(polyedge) / 3)))(polyedge))

            elif len(splits) == 2:
                one, two = list_split(
                    polyedge, [polyedge.index(vkey) for vkey in splits])
                half = one if len(one) > len(two) else two
                new_splits.append(half[int(floor(len(half) / 2))])

            for vkey in new_splits:
                fkey = list(self.vertex_faces(vkey))[0]
                for edge in self.face_halfedges(fkey):
                    if vkey in edge and not self.is_edge_on_boundary(*edge):
                        new_branches += [[
                            trimesh_face_circle(self, fkey)[0],
                            self.vertex_coordinates(vkey_2)
                        ] for vkey_2 in edge]
                        all_splits.update(edge)
                        break

        return new_branches
Esempio n. 4
0
    def branches_boundary(self):
        """Get new branch polylines from the Delaunay mesh boundaries split at the corner and plit vertices. Not part of the topological skeleton.

		Returns
		-------
		list
			List of polylines as list of point XYZ-coordinates.

		"""

        boundaries = [bdry + bdry[0:] for bdry in self.boundaries()]
        splits = self.corner_vertices() + self.split_vertices()
        split_boundaries = [
            split_boundary for boundary in boundaries
            for split_boundary in list_split(boundary, [
                boundary.index(split) for split in splits if split in boundary
            ])
        ]
        return [[self.vertex_coordinates(vkey) for vkey in boundary]
                for boundary in split_boundaries]
Esempio n. 5
0
def func_1(mesh, fix_xyz, kmax, damping):
    # geometrical processing: smooth to widen the strip with constraints at
    # kinks and along boundaries

    def callback(k, args):

        mesh, fixed, split_boundaries, split_boundaries_geom = args

        for vkey in mesh.vertices_on_boundary():
            if vkey not in fixed:
                for i, boundary in enumerate(split_boundaries):
                    if vkey in boundary:
                        xyz, dist = closest_point_on_polyline(
                            split_boundaries_geom[i],
                            mesh.vertex_coordinates(vkey))
                        attr = mesh.vertex[vkey]
                        attr['x'], attr['y'], attr['z'] = xyz
                        break

    fix_map = {geometric_key(xyz): [] for xyz in fix_xyz}
    for vkey in mesh.vertices():
        geom_key = geometric_key(mesh.vertex_coordinates(vkey))
        if geom_key in fix_map:
            fix_map[geom_key].append(vkey)

    fixed = []
    for vertices in fix_map.values():
        boundary_vertices = [
            vkey for vkey in vertices if mesh.is_vertex_on_boundary(vkey)
        ]
        if len(boundary_vertices) == 0:
            print('not adapted to fixed non-boundary vertices')
        elif len(boundary_vertices) == 1:
            fixed += boundary_vertices
        else:
            corner_vertices = [
                vkey for vkey in boundary_vertices
                if mesh.vertex_degree(vkey) == 2
            ]
            if len(corner_vertices) == 1:
                fixed += corner_vertices
            else:
                pass
                #print('not generalised yet')

    split_boundaries = []
    for boundary in mesh.boundaries():
        boundary.append(boundary[0])
        indices = [boundary.index(vkey) for vkey in fixed if vkey in boundary]
        split_boundaries += list_split(boundary, indices)
    split_boundaries_geom = {
        i: [mesh.vertex_coordinates(vkey) for vkey in boundary]
        for i, boundary in enumerate(split_boundaries)
    }

    callback_args = mesh, fixed, split_boundaries, split_boundaries_geom
    mesh_smooth_centroid(mesh,
                         fixed,
                         kmax=kmax,
                         damping=damping,
                         callback=callback,
                         callback_args=callback_args)
Esempio n. 6
0
def quadrangulate_face(mesh, fkey, sources):

    face_vertices = mesh.face_vertices(fkey)[:]

    # differentiate sources and non sources
    sources = [vkey for vkey in face_vertices if vkey in sources]
    non_sources = [vkey for vkey in face_vertices if vkey not in sources]
    new_sources = []

    if len(non_sources) == 4:
        a, b, c, d = non_sources
        ab, bc, cd, da = list_split(
            face_vertices + face_vertices[:1],
            [face_vertices.index(vkey) for vkey in non_sources])
        # add missing vertices
        for i, edges in enumerate([[ab, cd], [bc, da]]):
            uv, wx = edges
            # all cases

            if len(uv) == len(wx):
                # no subdivision needed
                continue

            elif len(uv) == 2 and len(wx) != 2:
                # subdivide uv
                n = len(wx) - len(uv) + 1
                new_points = [
                    mesh.edge_point(uv[0], uv[1],
                                    float(k) / float(n)) for k in range(n + 1)
                ][1:-1]
                new_vertices = [
                    mesh.add_vertex(attr_dict={
                        xyz: value
                        for xyz, value in zip(['x', 'y', 'z'], point)
                    }) for point in new_points
                ]
                new_sources += new_vertices
                if i == 0:
                    ab = [uv[0]] + new_vertices + [uv[-1]]
                elif i == 1:
                    bc = [uv[0]] + new_vertices + [uv[-1]]
                update_adjacent_face(mesh, uv[1], uv[0],
                                     list(reversed(new_vertices)))
            elif len(uv) != 2 and len(wx) == 2:
                # subdivide wx
                n = len(uv) - len(wx) + 1
                new_points = [
                    mesh.edge_point(wx[0], wx[1],
                                    float(k) / float(n)) for k in range(n + 1)
                ][1:-1]
                new_vertices = [
                    mesh.add_vertex(attr_dict={
                        xyz: value
                        for xyz, value in zip(['x', 'y', 'z'], point)
                    }) for point in new_points
                ]
                new_sources += new_vertices
                if i == 0:
                    cd = [wx[0]] + new_vertices + [wx[-1]]
                elif i == 1:
                    da = [wx[0]] + new_vertices + [wx[-1]]
                # update adjacent faces
                update_adjacent_face(mesh, wx[1], wx[0],
                                     list(reversed(new_vertices)))
            elif len(uv) != 2 and len(wx) != 2 and len(uv) != len(wx):
                pass
                # apply Takayama's work
                #print('not implemented yet')

        mesh.delete_face(fkey)

        discrete_coons_patch_mesh(mesh, ab, bc, list(reversed(cd)),
                                  list(reversed(da)))

    else:
        pass
        #print('not generalised yet')

    return new_sources
Esempio n. 7
0
def automated_smoothing_constraints(mesh,
                                    points=None,
                                    curves=None,
                                    surface=None,
                                    mesh2=None):
    """Apply automatically point, curve and surface constraints to the vertices of a mesh to smooth.

	Parameters
	----------
	mesh : Mesh
		The mesh to apply the constraints to for smoothing.
	points : list
		List of XYZ coordinates on which to constrain mesh vertices. Default is None.
	curves : list
		List of RhinoCurve objects on which to constrain mesh vertices. Default is None.
	surface : RhinoSurface
		A RhinoSurface object on which to constrain mesh vertices. Default is None.
	mesh2 : RhinoMesh
		A RhinoMesh object on which to constrain mesh vertices. Default is None.

	Returns
	-------
	constraints : dict
		A dictionary of mesh constraints for smoothing as vertex keys pointing to point, curve or surface objects.

	"""

    constraints = {}
    constrained_vertices = {}

    vertices = list(mesh.vertices())
    vertex_coordinates = [
        mesh.vertex_coordinates(vkey) for vkey in mesh.vertices()
    ]

    if points is not None and len(points) != 0:
        constrained_vertices.update({
            vertices[closest_point_in_cloud(rs.PointCoordinates(point),
                                            vertex_coordinates)[2]]: point
            for point in points
        })

    if mesh2 is not None:
        constraints.update({vkey: mesh2 for vkey in mesh.vertices()})

    if surface is not None:
        constraints.update({vkey: surface for vkey in mesh.vertices()})

    if curves is not None and len(curves) != 0:
        boundaries = [
            split_boundary for boundary in mesh.boundaries()
            for split_boundary in list_split(boundary, [
                boundary.index(vkey)
                for vkey in constrained_vertices.keys() if vkey in boundary
            ])
        ]
        boundary_midpoints = [
            Polyline([mesh.vertex_coordinates(vkey)
                      for vkey in boundary]).point(t=.5)
            for boundary in boundaries
        ]
        curve_midpoints = [
            rs.EvaluateCurve(curve, rs.CurveParameter(curve, .5))
            for curve in curves
        ]
        midpoint_map = {
            i: closest_point_in_cloud(boundary_midpoint, curve_midpoints)[2]
            for i, boundary_midpoint in enumerate(boundary_midpoints)
        }
        constraints.update({
            vkey: curves[midpoint_map[i]]
            for i, boundary in enumerate(boundaries) for vkey in boundary
        })

    if points is not None:
        constraints.update(constrained_vertices)

    return constraints