def angle_signed(self, other, normal): """Compute the signed angle between this vector and another vector. Parameters ---------- other : :class:`compas.geometry.Vector` or list The other vector. normal : :class:`compas.geometry.Vector` or list The plane's normal spanned by this and the other vector. Returns ------- float The signed angle between the two vectors. Examples -------- >>> from math import pi >>> u = Vector(1.0, 0.0, 0.0) >>> v = Vector(0.0, 1.0, 0.0) >>> u.angle_signed(v, Vector(0.0, 0.0, 1.0)) == 0.5 * pi True >>> u.angle_signed(v, Vector(0.0, 0.0, -1.0)) == -0.5 * pi True """ return angle_vectors_signed(self, other, normal)
def surface_calc(upper_board, lower_board, intersection): if upper_board.length_vector != lower_board.length_vector: len_intersection = lower_board.width wid_intersection = upper_board.width else: # for now we assume that they are parallel in this case, potential error source for later, though len_intersection = min(upper_board.length, lower_board.length) wid_intersection = min(upper_board.width, lower_board.width) dim1 = scale_vector(upper_board.length_vector, len_intersection * .5) dim2 = scale_vector(upper_board.width_vector, wid_intersection * .5) # this procedure is necessary only because of the glue path planning to make sure points are always ordered clockwise ang = angle_vectors_signed(dim1, dim2, Vector(0, 0, 1)) if ang > 0: pt1 = intersection + dim1 - dim2 pt2 = intersection + dim1 + dim2 pt3 = intersection - dim1 + dim2 pt4 = intersection - dim1 - dim2 else: pt1 = intersection - dim1 + dim2 pt2 = intersection + dim1 + dim2 pt3 = intersection + dim1 - dim2 pt4 = intersection - dim1 - dim2 intersection_surf = Polygon([pt1, pt2, pt3, pt4]) return intersection_surf
def branches_splitting_flipped_faces(self): """Add new branches to fix the problem of polyline patches that would form flipped faces in the decomposition mesh. Returns ------- new_branches : list List of polylines as list of point XYZ-coordinates. """ new_branches = [] centre_to_fkey = { geometric_key(trimesh_face_circle(self, fkey)[0]): fkey for fkey in self.faces() } # compute total rotation of polyline for polyline in self.branches_singularity_to_singularity(): angles = [ angle_vectors_signed(subtract_vectors(v, u), subtract_vectors(w, v), [0., 0., 1.]) for u, v, w in window(polyline, n=3) ] # subdivide once per angle limit in rotation if abs(sum(angles)) > self.flip_angle_limit: # the step between subdivision points in polylines (+ 2 for the extremities, which will be discarded) alone = len(self.compas_singular_faces()) == 0 n = floor(abs(sum(angles)) / self.flip_angle_limit) + 1 step = int(floor(len(polyline) / n)) # add new branches from corresponding face in Delaunay mesh seams = polyline[::step] if polyline[-1] != seams[-1]: if len(seams) == n + 1: del seams[-1] seams.append(polyline[-1]) if alone: seams = seams[0:-1] else: seams = seams[1:-1] for point in seams: fkey = centre_to_fkey[geometric_key(point)] for edge in self.face_halfedges(fkey): if not self.is_edge_on_boundary(*edge): new_branches += [[ trimesh_face_circle(self, fkey)[0], self.vertex_coordinates(vkey) ] for vkey in edge] break return new_branches
def signed_angle(u, v, normal=[0.0, 0.0, 1.0]): return angle_vectors_signed(u, v, normal)