def clip_line(line, boundaries): p0 = line[0] p1 = line[1] a = 0. b = 1. p0_all_safe, p1_all_safe = False, False for boundary in boundaries: n = boundary.normal th = boundary.threshold p0n = vec.dot(p0, n) p1n = vec.dot(p1, n) p0_safe = p0n >= th p1_safe = p1n >= th if p0_safe and p1_safe: a = 0 b = 1 p0_all_safe = True p1_all_safe = True break #print('p0,p1 safe',p0_safe,p1_safe) if p0_safe and (not p1_safe): t_intersect = (p0n - th) / (p0n - p1n) a = max(a, t_intersect) #print('move a to',a) if (not p0_safe) and p1_safe: t_intersect = (p0n - th) / (p0n - p1n) b = min(t_intersect, b) #print('move b to',b) p0_all_safe = (p0_all_safe or p0_safe) p1_all_safe = (p1_all_safe or p1_safe) #print('all_safe',p0_all_safe,p1_all_safe) #both endpoints visible if p0_all_safe and p1_all_safe: #return two lines if we've intersected the shape if a > 0 and b < 1: return [ Line(p0, vec.linterp(p0, p1, a)), Line(vec.linterp(p0, p1, b), p1) ] else: #return entire line if we haven't intersected the shape return [line] if p0_all_safe and (not p1_all_safe): return [Line(p0, vec.linterp(p0, p1, a))] if (not p0_all_safe) and p1_all_safe: return [Line(vec.linterp(p0, p1, b), p1)] #if neither point is visible, don't draw the line return []
def clip_line_plane(line, plane, small_z=0): p0 = line[0] p1 = line[1] n = plane.normal th = plane.threshold + small_z p0n = vec.dot(p0, n) p1n = vec.dot(p1, n) p0_safe = p0n >= th p1_safe = p1n >= th #if both vertices are behind, draw neither if (not p0_safe) and (not p1_safe): return None #both vertices in front if p0_safe and p1_safe: return line #if one of the vertices is behind the camera t_intersect = (p0n - th) / (p0n - p1n) intersect = vec.linterp(p0, p1, t_intersect) if (not p0_safe) and p1_safe: return Line(intersect, p1) else: return Line(p0, intersect)
def calc_boundary(face1, face2, origin): n1 = face1.normal n2 = face2.normal th1 = face1.threshold th2 = face2.threshold #k1 and k2 must be opposite signs k1 = vec.dot(n1, origin) - th1 k2 = vec.dot(n2, origin) - th2 t = k1 / (k1 - k2) n3 = vec.linterp(n1, n2, t) th3 = vec.linterp(th1, th2, t) return HyperPlane(n3, th3)
def draw_face_fuzz_old(face, camera, shape, shapes): #weights = np.random.uniform(size=[n_points,len(verts)]) #weights = weights/np.sum(weights,axis=1,keepdims=True) #points = np.dot(weights,verts) verts = [shape.verts[i] for i in face.get_verts(shape)] #points = [vec.linterp(verts[0], verts[1], t[0]) + vec.linterp(verts[0], verts[2], t[1]) for t in t_vals] if this.d == 3: points = [ vec.linterp(vec.linterp(verts[0], verts[1], t[0]), vec.linterp(verts[2], verts[3], t[0]), t[1]) for t in this.random_fuzz ] if this.d == 4: points = [ vec.linterp( vec.linterp(vec.linterp(verts[0], verts[1], t[0]), vec.linterp(verts[2], verts[3], t[0]), t[1]), vec.linterp(vec.linterp(verts[4], verts[5], t[0]), vec.linterp(verts[6], verts[7], t[0]), t[1]), t[2]) for t in this.random_fuzz ] #print(points.shape) if this.clipping: clipped = [False for i in range(len(points))] for clipping_shape in shapes: if (clipping_shape is not shape) and (not clipping_shape.transparent): new_clipped = [ Clipping.point_clipped(point, clipping_shape.boundaries) for point in points ] clipped = [ clip1 or clip2 for clip1, clip2 in zip(clipped, new_clipped) ] clipped_points = [ point for point, clip in zip(points, clipped) if (not clip) ] if len(clipped_points) < 1: return draw_points(camera, clipped_points, face.color) else: draw_points(camera, points, face.color)
def line_plane_intersect(line, plane): p0 = line[0] p1 = line[1] n = plane.normal th = plane.threshold p0n = vec.dot(p0, n) p1n = vec.dot(p1, n) #line is contained in plane if vec.isclose(p0n, 0) and vec.isclose(p1n, 0): return None #plane does not intersect line segment t = (p0n - th) / (p0n - p1n) if t < 0 or t > 1: return None return vec.linterp(p0, p1, t)
def scale_point(p, scale): return vec.linterp(face.center, p, scale)
def clip_line_cylinder(line, r, h, axis): def make_line(u0, u1, a0, a1, axis): return Line(vec.insert_index(u0, axis, a0), vec.insert_index(u1, axis, a1)) half_h = h / 2 v0 = line[0] v1 = line[1] #components parallel to axis a0 = v0[axis] a1 = v1[axis] #components perpendicular to axis u0 = vec.drop_index(v0, axis) u1 = vec.drop_index(v1, axis) #line is outside if (a0 > half_h and a1 > half_h) or (a0 < -half_h and a1 < -half_h): return None #clip lines to be within cylinder radius #would be nice if we could neatly merge this functionality with sphere clipping t_roots = sphere_t_intersect(Line(u0, u1), r) u0_in_circle = vec.dot(u0, u0) < r * r u1_in_circle = vec.dot(u1, u1) < r * r if u0_in_circle and u1_in_circle: circ_line = Line(u0, u1) else: if (not u0_in_circle) and (not u1_in_circle): #(extended) line does not intersect circle if t_roots is None: return None #check to see if segment intersecs #need only check one root to see if line segment intersects if t_roots[0] < 0 or t_roots[0] > 1: return None else: circ_line = Line(vec.linterp(u0, u1, t_roots[0]), vec.linterp(u0, u1, t_roots[1])) new_a0 = vec.linterp(a0, a1, t_roots[0]) new_a1 = vec.linterp(a0, a1, t_roots[1]) a0 = new_a0 a1 = new_a1 else: if u0_in_circle and (not u1_in_circle): #print("u0 in",tm,tp,line) circ_line = Line(u0, vec.linterp(u0, u1, t_roots[1])) a1 = vec.linterp(a0, a1, t_roots[1]) else: #print("u1 in",tm,tp,line) circ_line = Line(vec.linterp(u0, u1, t_roots[0]), u1) a0 = vec.linterp(a0, a1, t_roots[0]) new_line = make_line(circ_line[0], circ_line[1], a0, a1, axis) #clip top and bottom of cylinder d = vec.dim(v0) clipped_line = clip_line_plane(new_line, HyperPlane(-vec.one_hot(d, axis), -half_h)) if clipped_line is None: return None clipped_line = clip_line_plane(clipped_line, HyperPlane(vec.one_hot(d, axis), -half_h)) return clipped_line
def plane0_intersect(v1, v2, z0): #point of intersection with plane at x[-1] = z0 t = (v1[-1] - z0) / (v1[-1] - v2[-1]) return vec.linterp(v1, v2, t)