Beispiel #1
0
def surface_discrete_mapping(srf_guid, discretisation, minimum_discretisation = 5, crv_guids = [], pt_guids = []):
	"""Map the boundaries of a Rhino NURBS surface to planar poylines dicretised within some discretisation using the surface UV parameterisation.
	Curve and point feautres on the surface can be included.
	Parameters
	----------
	srf_guid : guid
		A surface guid.
	crv_guids : list
		List of guids of curves on the surface.
	pt_guids : list
		List of guids of points on the surface.
	discretisation : float
		The discretisation of the surface boundaries.
	minimum_discretisation : int
		The minimum discretisation of the surface boundaries.
	Returns
	-------
	tuple
		Tuple of the mapped objects: outer boundary, inner boundaries, polyline_features, point_features.
	"""

	srf = RhinoSurface.from_guid(srf_guid)

	# a boundary may be made of multiple boundary components and therefore checking for closeness and joining are necessary
	mapped_borders = []

	for i in [1, 2]:
		mapped_border = []

		for border_guid in srf.borders(type = i):
			points = [list(srf.point_xyz_to_uv(pt)) + [0.0] for pt in rs.DivideCurve(border_guid, max(int(rs.CurveLength(border_guid) / discretisation) + 1, minimum_discretisation))]
			
			if rs.IsCurveClosed(border_guid):
				points.append(points[0])
			
			mapped_border.append(points)
			rs.DeleteObject(border_guid)
		mapped_borders.append(mapped_border)

	outer_boundaries, inner_boundaries = [network_polylines(Network.from_lines([(u, v) for border in mapped_borders[i] for u, v in pairwise(border)])) for i in [0, 1]]
	
	# mapping of the curve features on the surface
	mapped_curves = []

	for crv_guid in crv_guids:

		curve = RhinoCurve.from_guid(crv_guid)
		points = [list(srf.point_xyz_to_uv(pt)) + [0.0] for pt in curve.divide(max(int(curve.length() / discretisation) + 1, minimum_discretisation))]
		
		if curve.is_closed():
			points.append(points[0])
		
		mapped_curves.append(points)

	polyline_features = network_polylines(Network.from_lines([(u, v) for curve in mapped_curves for u, v in pairwise(curve)]))

	# mapping of the point features onthe surface
	point_features = [list(srf.point_xyz_to_uv(rs.PointCoordinates(pt_guid))) + [0.0] for pt_guid in pt_guids]

	return outer_boundaries[0], inner_boundaries, polyline_features, point_features
def automated_smoothing_surface_constraints(mesh, surface):
	"""Apply automatically surface-related constraints to the vertices of a mesh to smooth: kinks, boundaries and surface.

	Parameters
	----------
	mesh : Mesh
		The mesh to apply the constraints to for smoothing.
	surface : Rhino surface guid
		A Rhino surface guid on which to constrain mesh vertices.

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

	"""

	surface = RhinoSurface.from_guid(surface)
	constraints = {}

	points = [rs.AddPoint(point) for point in surface.kinks()]
	curves = surface.borders(type = 0)

	constraints.update({vkey: surface.guid for vkey in mesh.vertices()})

	for vkey in mesh.vertices_on_boundary():
		xyz = mesh.vertex_coordinates(vkey)
		projections = {curve: distance_point_point(xyz, RhinoCurve.from_guid(curve).closest_point(xyz)) for curve in curves}
		constraints.update({vkey: min(projections, key = projections.get)})

	key_to_index = {i: vkey for i, vkey in enumerate(mesh.vertices_on_boundary())}
	vertex_coordinates = tuple(mesh.vertex_coordinates(vkey) for vkey in mesh.vertices_on_boundary())
	constraints.update({key_to_index[closest_point_in_cloud(rs.PointCoordinates(point), vertex_coordinates)[2]]: point for point in points})
	
	return constraints
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 Rhino curve guids on which to constrain mesh vertices. Default is None.
	surface : Rhino surface guid
		A Rhino surface guid on which to constrain mesh vertices. Default is None.
	mesh2 : Rhino mesh guid
		A Rhino mesh guid 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.

	"""

	if surface:
		surface = RhinoSurface.from_guid(surface)
	if curves:
		curves = [RhinoCurve.from_guid(curve) for curve in curves]
	if mesh2:
		mesh2 = RhinoMesh.from_guid(mesh2)

	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.guid for vkey in mesh.vertices()})

	if surface is not None:
		constraints.update({vkey: surface.guid 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]].guid for i, boundary in enumerate(boundaries) for vkey in boundary})
	
	if points is not None:
		constraints.update(constrained_vertices)

	return constraints
def customized_smoothing_constraints(mesh, constraints):
    """Add custom 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.
	constraints : dict
		A dictionary of mesh constraints for smoothing as vertex keys pointing to point, curve or surface objects.

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

	"""

    while True:

        guids = display_smoothing_constraints(mesh, constraints)
        vkeys = mesh_select_vertices(mesh)
        if len(vkeys) == 2 and rs.GetString(
                'get all polyedge?', strings=['True', 'False']) == 'True':
            u, v = vkeys
            vkeys = mesh.polyedge(u, v)

        if vkeys is None:
            break

        constraint = rs.GetString(
            'edit smoothing constraints?',
            strings=['point', 'curve', 'surface', 'exit'])

        rs.DeleteObjects(guids)

        if constraint is None or constraint == 'exit':
            break

        elif constraint == 'point':
            point = RhinoPoint.from_selection()
            constraints.update({vkey: point.guid for vkey in vkeys})

        elif constraint == 'curve':
            curve = RhinoCurve.from_selection()
            constraints.update({vkey: curve.guid for vkey in vkeys})

        elif constraint == 'surface':
            surface = RhinoSurface.from_selection()
            constraints.update({vkey: surface.guid for vkey in vkeys})

    return constraints
    def callback(k, args):

        mesh, constraints = args

        for vkey, constraint in constraints.items():
            if constraint is None:
                continue
            elif rs.ObjectType(constraint) == 1:
                x, y, z = RhinoPoint.from_guid(constraint).xyz
            elif rs.ObjectType(constraint) == 4:
                x, y, z = RhinoCurve.from_guid(constraint).closest_point(
                    mesh.vertex_coordinates(vkey))
            elif rs.ObjectType(constraint) == 8:
                x, y, z = RhinoSurface.from_guid(constraint).closest_point(
                    mesh.vertex_coordinates(vkey))
            elif rs.ObjectType(constraint) == 32:
                x, y, z = RhinoMesh.from_guid(constraint).closest_point(
                    mesh.vertex_coordinates(vkey))
            else:
                continue

            mesh.vertex[vkey]['x'] = x
            mesh.vertex[vkey]['y'] = y
            mesh.vertex[vkey]['z'] = z
def RunCommand(is_interactive):
    scene = get_scene()
    if not scene:
        return

    proxy = get_proxy()
    if not proxy:
        return

    delaunay = proxy.function('compas.geometry.delaunay_from_points_numpy')

    # Get input data.
    surf_guid = compas_rhino.select_surface("Select a surface to decompose.")
    if not surf_guid:
        return
    point_guids = compas_rhino.select_points(
        "Select points to include in the decomposition.")
    curve_guids = []

    compas_rhino.rs.HideObjects([surf_guid] + point_guids + curve_guids)

    surface = RhinoSurface.from_guid(surf_guid)
    curves = [RhinoCurve.from_guid(guid) for guid in curve_guids]
    points = [RhinoPoint.from_guid(guid) for guid in point_guids]

    # Compute the feature discretisation length.
    box = compas_rhino.rs.BoundingBox([surf_guid])
    diagonal = compas_rhino.rs.Distance(box[0], box[6])
    D = 0.05 * diagonal

    # Get the target length for the final quad mesh.
    L = compas_rhino.rs.GetReal(
        "Define the target edge length of the pattern.", 1.0)

    # Generate the pattern
    pattern = Pattern.from_surface_and_features(D,
                                                L,
                                                surf_guid,
                                                curve_guids,
                                                point_guids,
                                                delaunay=delaunay)

    scene.clear()
    scene.add(pattern, name='pattern')
    scene.update()

    kmax = 10

    # Constrain mesh components to the feature geometry.
    constraints = automated_smoothing_surface_constraints(pattern, surface)
    constraints.update(
        automated_smoothing_constraints(pattern,
                                        rhinopoints=points,
                                        rhinocurves=curves))

    while True:
        option = compas_rhino.rs.GetString("Smoothen the pattern?", "No",
                                           ["Yes", "No"])
        if not option:
            break
        if option != "Yes":
            break

        constrained_smoothing(pattern,
                              kmax=kmax,
                              damping=0.5,
                              constraints=constraints,
                              algorithm="area")
        scene.update()

    print('Pattern object successfully created. Input object has been hidden.')