Example #1
0
def smooth_network_length(network, lmin, lmax, fixed=None, kmax=1, d=0.5, callback=None, callback_args=None):
    fixed = fixed or []
    fixed = set(fixed)

    if callback:
        if not callable(callback):
            raise Exception('The callback is not callable.')

    for k in range(kmax):
        key_xyz = {key: network.vertex_coordinates(key) for key in network.vertices()}

        for key in network:
            if key in fixed:
                continue

            ep = key_xyz[key]
            points = []

            for nbr in network.vertex_neighbours(key):
                sp    = key_xyz[nbr]
                vec   = subtract_vectors(ep, sp)
                lvec  = length_vector(vec)
                scale = max(lmin, min(lvec, lmax))
                p     = add_vectors(sp, scale_vector(vec, scale / lvec))
                points.append(p)

            x, y, z = centroid_points(points)

            attr = network.vertex[key]
            attr['x'] += d * (x - ep[0])
            attr['y'] += d * (y - ep[1])
            attr['z'] += d * (z - ep[2])

        if callback:
            callback(network, k, callback_args)
Example #2
0
def draw_cylinders(cylinders: List[Dict],
                   collection: Union[Text, bpy.types.Collection] = None,
                   uv: int = 10) -> List[bpy.types.Object]:
    """Draw cylinder objects as mesh primitives."""
    from math import acos
    from math import atan2
    bpy.ops.mesh.primitive_cylinder_add(location=[0, 0, 0],
                                        radius=1,
                                        depth=1,
                                        vertices=uv)
    empty = bpy.context.object
    _link_object(empty, collection)
    objects = [0] * len(cylinders)
    for index, data in enumerate(cylinders):
        sp = data['start']
        ep = data['end']
        mp = centroid_points([sp, ep])
        radius = data.get('radius', 1.0)
        length = distance_point_point(sp, ep)
        obj = empty.copy()
        obj.name = data.get('name', 'cylinder')
        obj.rotation_euler[1] = acos((ep[2] - sp[2]) / length)
        obj.rotation_euler[2] = atan2(ep[1] - sp[1], ep[0] - sp[0])
        obj.location = mp
        obj.scale = ((radius, radius, length))
        rgb = data.get('color', [1.0, 1.0, 1.0])
        _set_object_color(obj, rgb)
        objects[index] = obj
    _link_objects(objects, collection)
    empty.hide_set(True)
    return objects
Example #3
0
    def vertex_normal(self, vertex):
        """Return the normal vector at the vertex as the weighted average of the
        normals of the neighboring faces.

        Parameters
        ----------
        key : int
            The identifier of the vertex.

        Returns
        -------
        list
            The components of the normal vector.
        """
        if not self.is_vertex_on_boundary(vertex):
            return

        halffaces = []
        for halfface in self.vertex_halffaces(vertex):
            if self.is_halfface_on_boundary(halfface):
                halffaces.append(halfface)

        vectors = [
            self.face_normal(halfface, False) for halfface in halffaces
            if halfface is not None
        ]
        return normalize_vector(centroid_points(vectors))
Example #4
0
def _face_adjacency(xyz, faces, nmax=10, radius=2.0):
    points = [centroid_points([xyz[index] for index in face]) for face in faces]
    k = min(len(faces), nmax)
    tree = cKDTree(points)
    _, closest = tree.query(points, k=k, n_jobs=-1)
    adjacency = {}
    for face, vertices in enumerate(faces):
        nbrs = []
        found = set()
        nnbrs = set(closest[face])
        for u, v in pairwise(vertices + vertices[0:1]):
            for nbr in nnbrs:
                if nbr == face:
                    continue
                if nbr in found:
                    continue
                for a, b in pairwise(faces[nbr] + faces[nbr][0:1]):
                    if v == a and u == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break
                for a, b in pairwise(faces[nbr] + faces[nbr][0:1]):
                    if u == a and v == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break
        adjacency[face] = nbrs
    return adjacency
Example #5
0
def kagome_polyedge_colouring(kagome):

    polyedges = kagome.polyedge_data

    edge_to_polyedge_index = {vkey: {} for vkey in kagome.vertices()}
    for i, polyedge in enumerate(polyedges):
        for u, v in pairwise(polyedge):
            edge_to_polyedge_index[u][v] = i
            edge_to_polyedge_index[v][u] = i

    vertices = [
        centroid_points([kagome.vertex_coordinates(vkey) for vkey in polyedge])
        for polyedge in polyedges
    ]

    edges = []
    for idx, polyedge in enumerate(polyedges):
        for vkey in polyedge:
            for vkey_2 in kagome.vertex_neighbors(vkey):
                idx_2 = edge_to_polyedge_index[vkey][vkey_2]
                if idx_2 != idx and idx < idx_2 and (idx, idx_2) not in edges:
                    edges.append((idx, idx_2))

    polyedge_network = Network.from_nodes_and_edges(vertices, edges)

    key_to_colour = vertex_coloring(polyedge_network.adjacency)

    return [key_to_colour[key] for key in sorted(key_to_colour.keys())]
Example #6
0
    def check_element_exists(self, nodes=None, xyz=None, virtual=False):
        """ Check if an element already exists based on nodes or centroid.

        Parameters
        ----------
        nodes : list
            Node numbers the element is connected to.
        xyz : list
            Direct co-ordinates of the element centroid to check.
        virtual: bool
            Is the element to be checked a virtual element.

        Returns
        -------
        int
            The element index if the element already exists, None if not.

        Notes
        -----
        - Geometric key check is made according to self.tol [m] tolerance.

        """

        if not xyz:
            xyz = centroid_points([self.node_xyz(node) for node in nodes])

        gkey = geometric_key(xyz, '{0}f'.format(self.tol))

        if virtual:
            return self.virtual_element_index.get(gkey, None)
        else:
            return self.element_index.get(gkey, None)
Example #7
0
    def draw_edgelabels(self, text=None, color=None):
        """Draw labels for a selection of edges.

        Parameters
        ----------
        text : dict, optional
            A dictionary of edge labels as edge-text pairs.
            The default value is ``None``, in which case every edge will be labelled with its key.
        color : tuple or dict of tuple, optional
            The color specification of the labels.
            The default color is the same as the default color for edges.

        Returns
        -------
        list
            The GUIDs of the created Rhino objects.

        """
        if text is None:
            edge_text = {(u, v): "{}-{}".format(u, v) for u, v in self.edges}
        elif isinstance(text, dict):
            edge_text = text
        else:
            raise NotImplementedError
        vertex_xyz = self.vertex_xyz
        edge_color = colordict(color, edge_text.keys(), default=self.default_edgecolor)
        labels = []
        for edge in edge_text:
            labels.append({
                'pos': centroid_points([vertex_xyz[edge[0]], vertex_xyz[edge[1]]]),
                'name': "{}.edgelabel.{}-{}".format(self.mesh.name, *edge),
                'color': edge_color[edge],
                'text': edge_text[edge]
            })
        return compas_rhino.draw_labels(labels, layer=self.layer, clear=False, redraw=False)
Example #8
0
def draw_lines(lines, layer=None, centroid=True):
    objects = [0] * len(lines)
    for index, data in enumerate(lines):
        sp = data['start']
        ep = data['end']
        mp = centroid_points([sp, ep]) if centroid else [0, 0, 0]
        name = data.get('name', 'line')
        curve = bpy.data.curves.new(name, type='CURVE')
        curve.dimensions = '3D'
        spline = curve.splines.new('NURBS')
        spline.points.add(2)
        spline.points[0].co = list(subtract_vectors(sp, mp)) + [1]
        spline.points[1].co = list(subtract_vectors(ep, mp)) + [1]
        spline.order_u = 1
        obj = bpy.data.objects.new(name, curve)
        obj.location = mp
        obj.data.fill_mode = 'FULL'
        obj.data.bevel_depth = data.get('width', 0.05)
        obj.data.bevel_resolution = 0
        obj.data.resolution_u = 20
        rgb = data.get('color') or [1.0, 1.0, 1.0]
        set_object_color(obj, rgb)
        objects[index] = obj
    link_objects(objects, layer=layer)
    return objects
Example #9
0
def draw_cylinders(cylinders, div=10, layer=None):
    # don't set the obvious defaults?
    bpy.ops.mesh.primitive_cylinder_add(location=[0, 0, 0],
                                        radius=1,
                                        depth=1,
                                        vertices=div)
    empty = bpy.context.active_object
    objects = [0] * len(cylinders)
    for index, data in enumerate(cylinders):
        sp = data['start']
        ep = data['end']
        mp = centroid_points([sp, ep])
        radius = data.get('radius', 1.0)
        length = distance_point_point(sp, ep)
        obj = empty.copy()
        obj.name = data.get('name', 'cylinder')
        # get this from geometry package
        obj.rotation_euler[1] = acos((ep[2] - sp[2]) / length)
        obj.rotation_euler[2] = atan2(ep[1] - sp[1], ep[0] - sp[0])
        obj.location = mp
        obj.scale = ((radius, radius, length))
        rgb = data.get('color') or [1.0, 1.0, 1.0]
        set_object_color(obj, rgb)
        objects[index] = obj
    delete_object(empty)
    link_objects(objects, layer=layer)
    return objects
Example #10
0
def draw_line(start=[0, 0, 0],
              end=[1, 1, 1],
              width=0.05,
              centroid=True,
              name='line',
              color=[1, 1, 1],
              layer=None):
    mp = centroid_points([start, end]) if centroid else [0, 0, 0]
    curve = bpy.data.curves.new(name, type='CURVE')
    curve.dimensions = '3D'
    object = bpy.data.objects.new(name, curve)
    object.location = mp
    spline = curve.splines.new('NURBS')
    spline.points.add(2)
    spline.points[0].co = list(subtract_vectors(start, mp)) + [1]
    spline.points[1].co = list(subtract_vectors(end, mp)) + [1]
    spline.order_u = 1
    object.data.fill_mode = 'FULL'
    object.data.bevel_depth = width
    object.data.bevel_resolution = 0
    object.data.resolution_u = 20
    object.data.materials.append(create_material(color=color))
    bpy.context.collection.objects.link(object)
    if layer:
        set_objects_layer(objects=[object], layer=layer)
    return object
Example #11
0
    def from_planes(cls, planes):
        """Construct a polyhedron from intersecting planes.

        Parameters
        ----------
        planes : list of :class:`compas.geometry.Plane` or list of (point, normal)

        Returns
        -------
        :class:`compas.geometry.Polyhedron`

        Examples
        --------
        >>> from compas.geometry import Plane
        >>> left = Plane([-1, 0, 0], [-1, 0, 0])
        >>> right = Plane([+1, 0, 0], [+1, 0, 0])
        >>> top = Plane([0, 0, +1], [0, 0, +1])
        >>> bottom = Plane([0, 0, -1], [0, 0, -1])
        >>> front = Plane([0, -1, 0], [0, -1, 0])
        >>> back = Plane([0, +1, 0], [0, +1, 0])
        >>> p = Polyhedron.from_planes([left, right, top, bottom, front, back])

        """
        from compas.geometry import Plane
        from compas.geometry import centroid_points
        planes = [Plane(point, normal) for point, normal in planes]
        interior = centroid_points([plane.point for plane in planes])
        return cls.from_halfspaces([plane.abcd for plane in planes], interior)
Example #12
0
def xdraw_pipes(pipes, div=8):
    """ Draw a set of pipes.

    Parameters:
        pipes (list): {'radius':, 'start':, 'end':, 'color':, 'name':, 'layer':}.
        div (int): Divisions around cross-section.

    Returns:
        list: Created pipe objects.
    """
    objects = []
    bpy.ops.mesh.primitive_cylinder_add(radius=1, depth=1, vertices=div, location=[0, 0, 0])
    object = bpy.context.object
    for pipe in pipes:
        radius = pipe.get('radius', 1)
        start = pipe.get('start', [0, 0, 0])
        end = pipe.get('end', [0, 0, 1])
        L = distance_point_point(start, end)
        pos = centroid_points([start, end])
        copy = object.copy()
        copy.name = pipe.get('name', 'pipe')
        copy.rotation_euler[1] = acos((end[2] - start[2]) / L)
        copy.rotation_euler[2] = atan2(end[1] - start[1], end[0] - start[0])
        copy.location = Vector(pos)
        copy.data = copy.data.copy()
        copy.scale = ((radius, radius, L))
        copy.show_wire = True
        copy.data.materials.append(bpy.data.materials[pipe.get('color', 'white')])
        set_objects_layer([copy], pipe.get('layer', 0))
        objects.append(copy)
    delete_objects([object])
    for object in objects:
        bpy.context.scene.objects.link(object)
    deselect_all_objects()
    return objects
Example #13
0
    def interface(self, interface):
        self._interface = interface

        faces = []
        xyz = interface['interface_points']

        f = len(xyz)

        if f < 3:
            pass

        elif f == 3:
            faces.append([0, 1, 2])

        elif f == 4:
            faces.append([0, 1, 2])
            faces.append([2, 3, 0])
        else:
            c = centroid_points(xyz)
            xyz.append(c)
            for a, b in pairwise(list(range(0, f))):
                faces.append([a, b, f])
            faces.append([b, 0, f])

        self._xyz = xyz
        self._faces = faces
Example #14
0
def structure_face_centers(structure):
    eks = radiating_faces(structure)
    centers = []
    for ek in eks:
        pl = [structure.nodes[nk].xyz() for nk in structure.elements[ek].nodes]
        centers.append(centroid_points(pl))
    return centers
Example #15
0
    def draw_facenormals(self, faces=None, color=(0, 255, 255), scale=1.0):
        """Draw the normals of the faces.

        Parameters
        ----------
        faces : list, optional
            A selection of face normals to draw.
            Default is to draw all face normals.
        color : tuple, optional
            The color specification of the normal vectors.
            The default color is cyan, ``(0, 255, 255)``.
        scale : float, optional
            Scale factor for the face normals.
            Default is ``1.0``.

        Returns
        -------
        list
            The GUIDs of the created Rhino objects.

        """
        vertex_xyz = self.vertex_xyz
        faces = faces or list(self.mesh.faces())
        lines = []
        for face in faces:
            a = centroid_points([vertex_xyz[vertex] for vertex in self.mesh.face_vertices(face)])
            n = self.mesh.face_normal(face)
            b = add_vectors(a, scale_vector(n, scale))
            lines.append({
                'start': a,
                'end': b,
                'name': "{}.facenormal.{}".format(self.mesh.name, face),
                'color': color,
                'arrow': 'end'})
        return compas_rhino.draw_lines(lines, layer=self.layer, clear=False, redraw=False)
Example #16
0
def polygon_normal_oriented(polygon, unitized=True):
    """Compute the oriented normal of any closed polygon (can be convex, concave or complex).

    Parameters
    ----------
    polygon : sequence
        The XYZ coordinates of the vertices/corners of the polygon.
        The vertices are assumed to be in order.
        The polygon is assumed to be closed:
        the first and last vertex in the sequence should not be the same.

    Returns
    -------
    list
        The weighted or unitized normal vector of the polygon.

    """
    p = len(polygon)
    assert p > 2, "At least three points required"
    w          = centroid_points(polygon)
    normal_sum = (0, 0, 0)

    for i in range(-1, len(polygon) - 1):
        u          = polygon[i]
        v          = polygon[i + 1]
        uv         = subtract_vectors(v, u)
        vw         = subtract_vectors(w, v)
        normal     = scale_vector(cross_vectors(uv, vw), 0.5)
        normal_sum = add_vectors(normal_sum, normal)

    if not unitized:
        return normal_sum

    return normalize_vector(normal_sum)
Example #17
0
    def add_element_to_element_index(self, key, nodes, virtual=False):
        """ Adds the element to the element_index dictionary.

        Parameters
        ----------
        key : int
            Prescribed element key.
        nodes : list
            Node numbers the element is connected to.
        virtual: bool
            If true, adds element to the virtual_element_index dictionary.

        Returns
        -------
        None

        """

        centroid = centroid_points([self.node_xyz(node) for node in nodes])
        gkey = geometric_key(centroid, '{0}f'.format(self.tol))

        if virtual:
            self.virtual_element_index[gkey] = key
        else:
            self.element_index[gkey] = key
Example #18
0
def polygon_area_footprint(polygon):
    """Compute the non-oriented area of a polygon (can be convex or concave).

    Parameters
    ----------
    polygon : list of lists
        A list of polygon point coordinates.

    Returns
    -------
    float
        The non-oriented area of the polygon.

    """
    area = 0
    w    = centroid_points(polygon)

    for i in range(-1, len(polygon) - 1):
        u      = polygon[i]
        v      = polygon[i + 1]
        uv     = subtract_vectors(v, u)
        vw     = subtract_vectors(w, v)
        normal = scale_vector(cross_vectors(uv, vw), 0.5)
        area   += length_vector(normal)

    return area
Example #19
0
 def center_assembly(self):
     xyz = self.assembly.get_vertices_attributes('xyz')
     cx, cy, cz = centroid_points(xyz)
     for key, attr in self.assembly.vertices(True):
         attr['x'] -= cx
         attr['y'] -= cy
         attr['z'] -= cz
Example #20
0
    def draw_edgelabels(self,
                        text: Optional[Dict[Tuple[int, int], str]] = None,
                        color: Optional[Union[str, RGBColor, List[RGBColor], Dict[int, RGBColor]]] = None
                        ) -> List[bpy.types.Object]:
        """Draw labels for a selection of edges.

        Parameters
        ----------
        text : dict, optional
            A dictionary of edge labels as edge-text pairs.
            The default value is ``None``, in which case every edge will be labeled with its key.
        color : rgb-tuple or dict of rgb-tuple
            The color specification of the labels.
            The default color is the same as the default color for edges.

        Returns
        -------
        list of :class:`bpy.types.Object`
        """
        if text is None:
            edge_text = {(u, v): "{}-{}".format(u, v) for u, v in self.edges}
        elif isinstance(text, dict):
            edge_text = text
        else:
            raise NotImplementedError
        edge_color = colordict(color, edge_text, default=self.default_edgecolor)
        labels = []
        for edge in edge_text:
            labels.append({
                'pos': centroid_points([self.node_xyz[edge[0]], self.node_xyz[edge[1]]]),
                'name': "{}.edgelabel.{}-{}".format(self.network.name, *edge),
                'text': edge_text[edge]
            })
        return compas_blender.draw_texts(labels, collection=self.edgelabelcollection, color=edge_color)
Example #21
0
 def radiating_face_centers(self):
     eks = self.radiating_faces()
     centers = []
     for ek in eks:
         pl = [self.nodes[nk].xyz() for nk in self.elements[ek].nodes]
         centers.append(centroid_points(pl))
     return centers
Example #22
0
def intersect_lines_colinear(l1, l2, tol):
    def are_segments_colinear(l1, l2, tol):
        a, b = l1
        d, c = l2
        return is_colinear(a, b, c, tol)
    if are_segments_colinear(l1, l2, tol):
        return centroid_points([l1[1], l2[0]])
Example #23
0
def planarize_mesh(mesh,
                   fixed=None,
                   kmax=100,
                   d=1.0,
                   callback=None,
                   callback_args=None):
    """Planarise the faces of a mesh.

    Planarisation is implemented as a two-step iterative procedure. At every
    iteration, faces are first individually projected to their best-fit plane,
    and then the vertices are projected to the centroid of the disconnected
    corners of the faces.

    Parameters:
        mesh
        fixed
        kmax
        d
        callback
        callback_args

    Returns:
        None

    """
    # planarize every face individually
    # by projecting all vertices onto the best-fit plane
    # reconnect the corners of the faces
    # by mapping the vertices to the centroids of the face corners

    if callback:
        if not callable(callback):
            raise Exception('The callback is not callable.')

    fixed = fixed or []
    fixed = set(fixed)

    for k in range(kmax):

        key_xyz = {key: [] for key in mesh.vertices()}

        for fkey in mesh.faces():
            points = mesh.face_coordinates(fkey)
            plane = bestfit_plane_from_points(points)
            projections = project_points_plane(points, plane)

            for index, key in enumerate(mesh.face_vertices(fkey)):
                key_xyz[key].append(projections[index])

        for key, attr in mesh.vertices(data=True):
            if key in fixed:
                continue

            x, y, z = centroid_points(key_xyz[key])
            attr['x'] = x
            attr['y'] = y
            attr['z'] = z

        if callback:
            callback(mesh, k, callback_args)
Example #24
0
def _face_adjacency(xyz, faces, nmax=10, radius=2.0):
    points = [centroid_points([xyz[index] for index in face]) for face in faces]
    tree = KDTree(points)
    closest = [tree.nearest_neighbors(point, nmax) for point in points]
    closest = [[index for _, index, _ in nnbrs] for nnbrs in closest]
    adjacency = {}
    for face, vertices in enumerate(faces):
        nbrs = []
        found = set()
        nnbrs = set(closest[face])
        for u, v in pairwise(vertices + vertices[0:1]):
            for nbr in nnbrs:
                if nbr == face:
                    continue
                if nbr in found:
                    continue
                for a, b in pairwise(faces[nbr] + faces[nbr][0:1]):
                    if v == a and u == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break
                for a, b in pairwise(faces[nbr] + faces[nbr][0:1]):
                    if u == a and v == b:
                        nbrs.append(nbr)
                        found.add(nbr)
                        break
        adjacency[face] = nbrs
    return adjacency
Example #25
0
def draw_lines(lines: List[Dict],
               collection: Union[Text, bpy.types.Collection] = None,
               centroid: bool = True) -> List[bpy.types.Object]:
    """Draw line objects."""
    L = len(lines)
    N = len(str(L))
    objects = [0] * L
    for index, data in enumerate(lines):
        sp = data['start']
        ep = data['end']
        origin = centroid_points([sp, ep]) if centroid else [0, 0, 0]
        name = data.get('name', f'L.{index:0{N}d}')
        curve = bpy.data.curves.new(name, type='CURVE')
        curve.dimensions = '3D'
        spline = curve.splines.new('POLY')
        spline.points.add(1)
        spline.points[0].co = subtract_vectors(sp, origin) + [1.0]
        spline.points[1].co = subtract_vectors(ep, origin) + [1.0]
        spline.order_u = 1
        obj = bpy.data.objects.new(name, curve)
        obj.location = origin
        obj.data.fill_mode = 'FULL'
        obj.data.bevel_depth = data.get('width', 0.05)
        obj.data.bevel_resolution = 0
        obj.data.resolution_u = 20
        rgb = data.get('color', [1.0, 1.0, 1.0])
        _set_object_color(obj, rgb)
        objects[index] = obj
    _link_objects(objects, collection)
    return objects
Example #26
0
def smooth_mesh_centroid(mesh,
                         fixed=None,
                         kmax=1,
                         d=1.0,
                         callback=None,
                         callback_args=None):
    """"""

    if callback:
        if not callable(callback):
            raise Exception('Callback is not callable.')

    fixed = fixed or []
    fixed = set(fixed)

    for k in range(kmax):
        key_xyz = {key: mesh.vertex_coordinates(key) for key in mesh}

        for key in mesh.vertices():
            if key in fixed:
                continue

            p = key_xyz[key]

            nbrs = mesh.vertex_neighbours(key)
            c = centroid_points([key_xyz[nbr] for nbr in nbrs])

            # update
            attr = mesh.vertex[key]
            attr['x'] += d * (c[0] - p[0])
            attr['y'] += d * (c[1] - p[1])
            attr['z'] += d * (c[2] - p[2])

        if callback:
            callback(mesh, k, callback_args)
Example #27
0
def draw_pipes(pipes: List[Dict],
               collection: Union[Text, bpy.types.Collection] = None,
               centroid: bool = True,
               smooth: bool = True) -> List[bpy.types.Object]:
    """Draw polyline objects."""
    P = len(pipes)
    N = len(str(P))
    objects = [0] * P
    for index, data in enumerate(pipes):
        points = data['points']
        origin = centroid_points(points) if centroid else [0, 0, 0]
        name = data.get('name', f'POLY.{index:0{N}d}')
        curve = bpy.data.curves.new(name, type='CURVE')
        curve.dimensions = '3D'
        curve.fill_mode = 'FULL'
        curve.bevel_depth = data.get('width', 0.05)
        curve.bevel_resolution = 0
        curve.resolution_u = 20
        curve.use_fill_caps = True
        if smooth:
            spline = curve.splines.new('NURBS')
        else:
            spline = curve.splines.new('POLY')
        spline.points.add(len(points) - 1)
        for i, point in enumerate(points):
            spline.points[i].co = subtract_vectors(point, origin) + [1.0]
        spline.order_u = 1
        obj = bpy.data.objects.new(name, curve)
        obj.location = origin
        rgb = data.get('color', [1.0, 1.0, 1.0])
        _set_object_color(obj, rgb)
        objects[index] = obj
    _link_objects(objects, collection)
    return objects
Example #28
0
 def center_mesh(self):
     xyz = [self.mesh.vertex_coordinates(key) for key in self.mesh.vertices()]
     cx, cy, cz = centroid_points(xyz)
     for key, attr in self.mesh.vertices(True):
         attr['x'] -= cx
         attr['y'] -= cy
         attr['z'] -= cz
Example #29
0
    def check_element_exists(self, nodes, xyz=None):
        """ Check if an element already exists based on the nodes it connects to or its centroid.

        Parameters
        ----------
        nodes : list
            Node numbers the element is connected to.
        xyz : list
            Direct co-ordinates of the element centroid to check.

        Returns
        -------
        int
            The element index if the element already exists, None if not.

        Notes
        -----
        - Geometric key check is made according to self.tol [m] tolerance.

        """

        if not xyz:
            xyz = centroid_points([self.node_xyz(node) for node in nodes])
        gkey = geometric_key(xyz, '{0}f'.format(self.tol))
        return self.element_index.get(gkey, None)
Example #30
0
def smooth_network_centroid(network, fixed=None, kmax=1, d=0.5, callback=None, callback_args=None):
    """Smooth a network using per vertex the centroid of its neighbours.

    Parameters:
        network (compas.datastructures.network.Network): The network object.
        fixed (list): Optional.
            The fixed vertices of the network. Default is ``None``.
        kmax (int): Optional.
            The maximum number of iterations. Default is ``1``.
        d (float): Optional.
            The damping factor. Default is ``0.5``.
        callback (callable): Optional.
            A user-defined callback function to be executed after every iteration.
            Default is ``None``.

    Raises:
        Exception: If a callback is provided, but not callable.

    Example:

        .. plot::
            :include-source:

            import compas
            from compas.datastructures.network import Network
            from compas.datastructures.network.algorithms import smooth_network_centroid

            network  = Network.from_obj(compas.get_data('grid_irregular.obj'))

            smooth_network_centroid(network, fixed=network.leaves(), kmax=10)

            network.plot()

    """
    fixed = fixed or []
    fixed = set(fixed)

    if callback:
        if not callable(callback):
            raise Exception('The callback is not callable.')

    for k in range(kmax):
        key_xyz = {key: network.vertex_coordinates(key) for key in network.vertices()}

        for key in network:
            if key in fixed:
                continue

            nbrs       = network.vertex_neighbours(key)
            points     = [key_xyz[nbr] for nbr in nbrs]
            cx, cy, cz = centroid_points(points)
            x, y, z    = key_xyz[key]

            attr       = network.vertex[key]
            attr['x'] += d * (cx - x)
            attr['y'] += d * (cy - y)
            attr['z'] += d * (cz - z)

        if callback:
            callback(network, k, callback_args)