def __init__(self, start, direction, begin_entity, side=DRAG_END): global drag_connection self.p0 = start self.p1 = direction self.p2 = self.p3 = vec2.add([1, 1], start) self.in_entity = None self.out_entity = None self.depth = 0 self.drag = side if side == DRAG_END: self.p0 = start self.p1 = vec2.add(start, direction) self.p2 = self.p3 = start self.in_entity = begin_entity drag_connection = self elif side == DRAG_BEGINNING: self.p3 = start self.p2 = vec2.add(start, direction) self.p0 = self.p1 = start self.out_entity = begin_entity drag_connection = self self.locked = False
def calc_spline_points(apos, avec, bpos, bvec, num_divs, vec_scale): curv = [apos] for i in range(1, num_divs): t = float(i) / num_divs pos = vec2.add(vec2.scale(h0(t), apos), vec2.scale(h1(t), bpos)) vec = vec2.add(vec2.scale(g0(t), (avec[1], -avec[0])), vec2.scale(g1(t), (bvec[1], -bvec[0]))) pos = vec2.scale(vec_scale, vec, pos) curv.append(pos) curv.append(bpos) return curv
def update_endpoint(self, end, new_endpoint): if end == DRAG_BEGINNING: diff = vec2.sub(new_endpoint, self.p0) self.p0 = new_endpoint self.p1 = vec2.add(diff, self.p1) if end == DRAG_END: diff = vec2.sub(new_endpoint, self.p3) self.p3 = new_endpoint self.p2 = vec2.add(diff, self.p2)
def mouse_drag(self, mouse_x, mouse_y): global entities, drag_entity if drag_entity == self: dx = mouse_x - self.x - self.drag_offset[0] dy = mouse_y - self.y - self.drag_offset[1] self.x = self.sprite.x = mouse_x - self.drag_offset[0] self.y = self.sprite.y = mouse_y - self.drag_offset[1] self.attach_points = [ vec2.add((dx, dy), point) for point in self.attach_points ] self.hover = NONE for i in range(3): connection = self.connections[i] if connection: connection.update_endpoint(in_out_direction[self.kind][i], self.attach_points[i]) if mouse_x < 0 or mouse_x > window.width or mouse_y < 0 or mouse_y > window.height: for connection in self.connections: if connection: connection.remove() entities.remove(self) drag_entity = None del (self)
def end_drag(self, end, direction, end_entity): global drag_connection if self.drag == DRAG_END: self.p2 = vec2.add(end, direction) self.p3 = end self.out_entity = end_entity elif self.drag == DRAG_BEGINNING: self.p1 = vec2.add(end, direction) self.p0 = end self.in_entity = end_entity self.drag = NONE drag_connection = None
def move_mods(base_pos, base_angle, mods): mrot = mat2.rotate(base_angle) for vals in mods: name, pos, angle = vals[:3] npos = vec2.add(base_pos, vec2.mult(mrot, pos)) nangle = base_angle + angle if name == None: move_mods(npos, nangle, vals[3]) else: set_mod_pos_angle(name, npos, nangle)
def drawRect(pnts, layer, R=75, width=2): if R > 0: arcs = [] for idx, a in enumerate(pnts): b = pnts[idx - 1] vec = vec2.sub(b, a) length = vec2.length(vec) delta = vec2.scale(R / length, vec) na = vec2.add(a, delta) nb = vec2.sub(b, delta) ctr = vec2.add(nb, (delta[1], -delta[0])) arcs.append((ctr, na, nb)) add_line(na, nb, layer, width) for idx, (ctr, na, nb) in enumerate(arcs): arc = add_arc2(ctr, nb, arcs[idx - 1][1], -90, layer, width) # print( "na ", pnt.mils2unit( vec2.round( na ) ) ) # print( "start", arc.GetArcStart() ) # print( "nb ", pnt.mils2unit( vec2.round( nb ) ) ) # print( "end ", arc.GetArcEnd() ) else: for idx, a in enumerate(pnts): b = pnts[idx - 1] add_line(a, b, layer, width)
def add_wire_zigzag(pos_a, pos_b, angle, delta_angle, net, layer, width, radius): mid_pos = vec2.scale(0.5, vec2.add(pos_a, pos_b)) dir = vec2.rotate(-angle) mid_dir1 = vec2.rotate(-angle + delta_angle) mid_dir2 = vec2.rotate(-angle - delta_angle) _, ka1, _ = vec2.find_intersection(pos_a, dir, mid_pos, mid_dir1) _, ka2, _ = vec2.find_intersection(pos_a, dir, mid_pos, mid_dir2) mid_angle = (angle - delta_angle) if abs(ka1) < abs(ka2) else (angle + delta_angle) add_wire_directed((pos_a, angle), (mid_pos, mid_angle), net, layer, width, radius) add_wire_directed((pos_b, angle), (mid_pos, mid_angle), net, layer, width, radius)
def calc_bezier_points(pnts, num_divs, debug=False): num_pnts = len(pnts) tmp = [(0, 0) for n in range(num_pnts)] curv = [pnts[0]] for i in range(1, num_divs): t = float(i) / num_divs s = 1 - t for n in range(num_pnts): tmp[n] = pnts[n] for L in range(num_pnts - 1, 0, -1): for n in range(L): tmp[n] = vec2.scale(s, tmp[n], vec2.scale(t, tmp[n + 1])) curv.append(tmp[0]) curv.append(pnts[-1]) #add_lines( curv, layer, width ) if debug: # debug for pnt in pnts: add_arc(pnt, vec2.add(pnt, (20, 0)), 360, 'F.Fab', 4) return curv
def draw_corner(cnr_type, a, cnr_data, b, layer, width, dump=False): apos, aangle = a bpos, bangle = b avec = vec2.rotate(aangle) bvec = vec2.rotate(bangle + 180) curv = None if cnr_type != Bezier and abs(vec2.dot(avec, bvec)) > 0.999: cnr_type = Line #print( avec, bvec ) if cnr_type == Line: add_line(apos, bpos, layer, width) elif cnr_type == Linear: xpos, alen, blen = vec2.find_intersection(apos, avec, bpos, bvec) if cnr_data == None: add_line(apos, xpos, layer, width) add_line(bpos, xpos, layer, width) else: delta = cnr_data[0] #print( delta, alen, xpos ) amid = vec2.scale(alen - delta, avec, apos) bmid = vec2.scale(blen - delta, bvec, bpos) add_line(apos, amid, layer, width) add_line(bpos, bmid, layer, width) add_line(amid, bmid, layer, width) elif cnr_type == Bezier: num_data = len(cnr_data) alen = cnr_data[0] blen = cnr_data[-2] ndivs = cnr_data[-1] apos2 = vec2.scale(alen, avec, apos) bpos2 = vec2.scale(blen, bvec, bpos) pnts = [apos, apos2] if num_data > 3: for pt in cnr_data[1:num_data - 2]: pnts.append(pt) pnts.append(bpos2) pnts.append(bpos) curv = calc_bezier_points(pnts, ndivs) add_lines(curv, layer, width) elif cnr_type == BezierRound: radius = cnr_data[0] # _, alen, blen = vec2.find_intersection( apos, avec, bpos, bvec ) # debug = False # if alen <= radius: # print( 'BezierRound: alen < radius, {} < {}, at {}'.format( alen, radius, apos ) ) # debug = True # if blen <= radius: # print( 'BezierRound: alen < radius, {} < {}, at {}'.format( blen, radius, bpos ) ) # debug = True # amid = vec2.scale( alen - radius, avec, apos ) # bmid = vec2.scale( blen - radius, bvec, bpos ) # add_line( apos, amid, layer, width ) # add_line( bpos, bmid, layer, width ) # angle = vec2.angle( avec, bvec ) # if angle < 0: # #angle += 360 # angle *= -1 # ndivs = int( round( angle / 4.5 ) ) # #print( 'BezierRound: angle = {}, ndivs = {}'.format( angle, ndivs ) ) # coeff = (math.sqrt( 0.5 ) - 0.5) / 3 * 8 # #print( 'coeff = {}'.format( coeff ) ) # actrl = vec2.scale( alen + (coeff - 1) * radius, avec, apos ) # bctrl = vec2.scale( blen + (coeff - 1) * radius, bvec, bpos ) # pnts = [amid, actrl, bctrl, bmid] curv = calc_bezier_round_points(apos, avec, bpos, bvec, radius) add_lines(curv, layer, width) elif cnr_type == Round: radius = cnr_data[0] # print( 'Round: radius = {}'.format( radius ) ) # print( apos, avec, bpos, bvec ) xpos, alen, blen = vec2.find_intersection(apos, avec, bpos, bvec) # print( xpos, alen, blen ) debug = False if not is_supported_round_angle(aangle): pass #print( 'Round: warning aangle = {}'.format( aangle ) ) #debug = True if not is_supported_round_angle(bangle): pass #print( 'Round: warning bangle = {}'.format( bangle ) ) #debug = True if alen < radius: print('Round: alen < radius, {} < {}'.format(alen, radius)) debug = True if blen < radius: print('Round: blen < radius, {} < {}'.format(blen, radius)) debug = True if debug: add_arc(xpos, vec2.add(xpos, (10, 0)), 360, layer, width) return b, curv angle = vec2.angle(avec, bvec) angle = math.ceil(angle * 10) / 10 tangent = math.tan(abs(angle) / 2 / 180 * math.pi) side_len = radius / tangent # print( 'angle = {}, radius = {}, side_len = {}, tangent = {}'.format( angle, radius, side_len, tangent ) ) amid = vec2.scale(-side_len, avec, xpos) bmid = vec2.scale(-side_len, bvec, xpos) add_line(apos, amid, layer, width) add_line(bpos, bmid, layer, width) aperp = (-avec[1], avec[0]) if angle >= 0: ctr = vec2.scale(-radius, aperp, amid) add_arc2(ctr, bmid, amid, 180 - angle, layer, width) else: ctr = vec2.scale(+radius, aperp, amid) add_arc2(ctr, amid, bmid, 180 + angle, layer, width) elif cnr_type == Spline: vec_scale = cnr_data[0] ndivs = int(round(vec2.distance(apos, bpos) / 2.0)) avec = vec2.rotate(aangle + 90) bvec = vec2.rotate(bangle - 90) curv = calc_spline_points(apos, avec, bpos, bvec, ndivs, vec_scale) add_lines(curv, layer, width) return b, curv
def sum_pos(derby): return reduce(lambda x, y: vec2.add(x, y['pos']), derby, vec2.zero)
def sum_vel(derby): return reduce(lambda x, y: vec2.add(x, y['vel']), derby, vec2.zero)
def draw_thick_cubic_bezier(points, width, color): t = 0.0 curve_points = [] while t <= 1.0: x = points[0][0] * t * t * t + 3 * points[1][0] * t * t * ( 1 - t) + 3 * points[2][0] * t * (1 - t) * ( 1 - t) + points[3][0] * (1 - t) * (1 - t) * (1 - t) y = points[0][1] * t * t * t + 3 * points[1][1] * t * t * ( 1 - t) + 3 * points[2][1] * t * (1 - t) * ( 1 - t) + points[3][1] * (1 - t) * (1 - t) * (1 - t) curve_points.append((x, y)) t += 0.01 outer_points = [] outer_tex_coords = [] inner_points = [] inner_tex_coords = [] ortho_vector = vec2.norm( vec2.sub(curve_points[1], curve_points[0]) ) #todo SOLVED: What happens when two points are in the same spot? Two points never will be in the same spot, thanks to the direction always being added onto the endpoint. ortho_vector[0], ortho_vector[1] = -1 * ortho_vector[1], ortho_vector[0] ortho_vector = vec2.mul(ortho_vector, width) inner_points.append(vec2.sub(curve_points[0], ortho_vector)) outer_points.append(vec2.add(curve_points[0], ortho_vector)) diff = vec2.sub(inner_points[-1], vec2.vecint(inner_points[-1])) projected_diff = -vec2.inner(ortho_vector, diff) / vec2.abs(ortho_vector) inner_tex_coords.extend([0.0, 1.0 - projected_diff / width / 2, 0.0]) diff = vec2.sub(outer_points[-1], vec2.vecint(outer_points[-1])) projected_diff = -vec2.inner(ortho_vector, diff) / vec2.abs(ortho_vector) outer_tex_coords.extend([0.0, (1 - projected_diff) / width / 2, 0.0]) r = 1.0 for i in range(1, len(curve_points) - 1): ortho_vector = vec2.norm( vec2.sub(curve_points[i + 1], curve_points[i - 1])) ortho_vector[0], ortho_vector[1] = -1 * ortho_vector[1], ortho_vector[ 0] ortho_vector = vec2.mul(ortho_vector, width) inner_points.append(vec2.sub(curve_points[i], ortho_vector)) outer_points.append(vec2.add(curve_points[i], ortho_vector)) diff = vec2.sub(inner_points[-1], vec2.vecint(inner_points[-1])) projected_diff = -vec2.inner(ortho_vector, diff) / vec2.abs(ortho_vector) inner_tex_coords.extend([r, 1.0 - projected_diff / width / 2, 0.0]) diff = vec2.sub(outer_points[-1], vec2.vecint(outer_points[-1])) projected_diff = -vec2.inner(ortho_vector, diff) / vec2.abs(ortho_vector) outer_tex_coords.extend([r, (1 - projected_diff) / width / 2, 0.0]) r = -r + 1 #make r alternate between 0 and 1 ortho_vector = vec2.norm(vec2.sub(curve_points[-1], curve_points[-2])) ortho_vector[0], ortho_vector[1] = -1 * ortho_vector[1], ortho_vector[0] ortho_vector = vec2.mul(ortho_vector, width) inner_points.append(vec2.sub(curve_points[-1], ortho_vector)) outer_points.append(vec2.add(curve_points[-1], ortho_vector)) diff = vec2.sub(inner_points[-1], vec2.vecint(inner_points[-1])) projected_diff = -vec2.inner(ortho_vector, diff) / vec2.abs(ortho_vector) inner_tex_coords.extend([r, 1.0 - projected_diff / width / 2, 0.0]) diff = vec2.sub(outer_points[-1], vec2.vecint(outer_points[-1])) projected_diff = -vec2.inner(ortho_vector, diff) / vec2.abs(ortho_vector) outer_tex_coords.extend([r, (1 - projected_diff) / width / 2, 0.0]) all_points = [] tex_coords = [] tex_coords.extend(inner_tex_coords) tex_coords.extend(outer_tex_coords) for point in inner_points: x = int(point[0]) y = int(point[1]) #diff = vec2.abs((x-point[0], y-point[1])) #if bit == True: # tex_coords.extend([0.0, 1.0-diff/a, 0.0]) #else: # tex_coords.extend([1.0, 1.0-diff/a, 0.0]) #bit ^= True all_points.extend([x, y]) for point in outer_points: x = int(point[0]) y = int(point[1]) #if bit == True: # tex_coords.extend([0.0, (1-diff)/a, 0.0]) #else: # tex_coords.extend([1.0, (1-diff)/a, 0.0]) #bit ^= True all_points.extend(point) all_points = [int(p) for p in all_points] all_points = tuple(all_points) indices = [] l = len(inner_points) for i in range(l - 1): indices.append(i) indices.append(i + 1) indices.append(i + l) indices.append(i + 1) indices.append(i + 1 + l) indices.append(i + l) glEnable(gradtex.target) glBindTexture(gradtex.target, gradtex.id) pyglet.graphics.draw_indexed( len(all_points) / 2, pyglet.gl.GL_TRIANGLES, indices, ('v2i', all_points), ('t3f', tuple(tex_coords)) #('c4f', color*(len(all_points)/2)) )
def update(vehicle): return new(vec2.add(vehicle['pos'], vehicle['vel']), vehicle['vel'])