def add_wire_straight(pnts, net, layer, width, radius=0): rpnts = [] for idx, curr in enumerate(pnts): if idx == 0 or idx + 1 == len(pnts): # first or last rpnts.append(curr) continue prev = pnts[idx - 1] next = pnts[idx + 1] vec_a = vec2.sub(prev, curr) vec_b = vec2.sub(next, curr) len_a = vec2.length(vec_a) len_b = vec2.length(vec_b) length = min(abs(radius), len_a / 2 if idx - 1 > 0 else len_a, len_b / 2 if idx + 1 < len(pnts) - 1 else len_b) if length < 10**(-PointDigits): rpnts.append(curr) else: if radius < 0: # and abs( vec2.dot( vec_a, vec_b ) ) < len_a * len_b * 0.001: # bezier circle num_divs = 15 cef = (math.sqrt(0.5) - 0.5) / 3 * 8 bpnts = [] bpnts.append(vec2.scale(length / len_a, vec_a, curr)) bpnts.append(vec2.scale(length / len_a * cef, vec_a, curr)) bpnts.append(vec2.scale(length / len_b * cef, vec_b, curr)) bpnts.append(vec2.scale(length / len_b, vec_b, curr)) num_pnts = len(bpnts) tmp = [(0, 0) for n in range(num_pnts)] rpnts.append(bpnts[0]) for i in range(1, num_divs): t = float(i) / num_divs s = 1 - t for n in range(num_pnts): tmp[n] = bpnts[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])) rpnts.append(tmp[0]) rpnts.append(bpnts[-1]) else: rpnts.append(vec2.scale(length / len_a, vec_a, curr)) rpnts.append(vec2.scale(length / len_b, vec_b, curr)) for idx, curr in enumerate(rpnts): if idx == 0: continue prev = rpnts[idx - 1] if vec2.distance(prev, curr) > 0.01: add_track(prev, curr, net, layer, width)
def W(r, h): # :: Num ''' A weighting function (kernel) for the contribution of each neighbor to a particle's density. Forms a nice smooth gradient from the center of a particle to H, where it's 0 ''' assert isinstance(r, Vec2) assert isinstance(h, Num) if 0 < length(r) <= h: return 315/(64 * pi * h**9) * (h**2 - length(r)**2)**3 else: return 0 # Typecheck assert isinstance(ret, Num) return ret
def intersectCircleCircle(c0P, c0R, c1P, c1R): v = vec2.sub(c1P, c0P) d = vec2.length(v) R = c0R r = c1R try: x = (d * d - r * r + R * R) / (2 * d) except ZeroDivisionError: if R < r: return 'inside', () elif r > R: return 'outside', () else: return 'coincident', () k = R * R - x * x if k < 0: if x < 0: return 'inside', () else: return 'outside', () else: y = math.sqrt(k) return 'intersect', (vec2.toangle(v), vec2.toangle((x, y)))
def intersectCircleCircle(c0P, c0R, c1P, c1R): v = vec2.sub(c1P, c0P) d = vec2.length(v) R = c0R r = c1R try: x = (d*d - r*r + R*R)/(2*d) except ZeroDivisionError: if R<r: return 'inside',() elif r>R: return 'outside',() else: return 'coincident',() k = R*R - x*x if k<0: if x<0: return 'inside',() else: return 'outside',() else: y = math.sqrt(k) return 'intersect',(vec2.toangle(v),vec2.toangle((x,y)))
def W(r, h): # :: Num ''' A weighting function (kernel) for the contribution of each neighbor to a particle's density. Forms a nice smooth gradient from the center of a particle to H, where it's 0 ''' assert isinstance(r, Vec2) assert isinstance(h, Num) if 0 < length(r) <= h: return 315 / (64 * pi * h**9) * (h**2 - length(r)**2)**3 else: return 0 # Typecheck assert isinstance(ret, Num) return ret
def laplacian_W_viscosity(r, h): # :: Num ''' The laplacian of a weighting function that tends towards infinity when approching 0 (slows down particles moving faster than their neighbors) ''' len_r = length(r) if 0 < len_r <= h: ret = 45/(2 * pi * h**5) * (1 - len_r/h) else: ret = 0 assert isinstance(ret, Num) return ret
def laplacian_W_viscosity(r, h): # :: Num ''' The laplacian of a weighting function that tends towards infinity when approching 0 (slows down particles moving faster than their neighbors) ''' len_r = length(r) if 0 < len_r <= h: ret = 45 / (2 * pi * h**5) * (1 - len_r / h) else: ret = 0 assert isinstance(ret, Num) return ret
def gradient_Wspiky(r, h): # :: Vec2 ''' Gradient ( that is, Vec2(dx, dy) ) of a weighting function for a particle's pressure. This weight function is spiky (not flat or smooth at x=0) so particles close together repel strongly ''' len_r = length(r) if 0 < len_r <= h: ret = -1 * r * (45/(pi * h**6 * len_r)) * (h - len_r)**2 else: ret = Vec2(0, 0) assert isinstance(ret, Vec2) return ret
def gradient_Wspiky(r, h): # :: Vec2 ''' Gradient ( that is, Vec2(dx, dy) ) of a weighting function for a particle's pressure. This weight function is spiky (not flat or smooth at x=0) so particles close together repel strongly ''' len_r = length(r) if 0 < len_r <= h: ret = -1 * r * (45 / (pi * h**6 * len_r)) * (h - len_r)**2 else: ret = Vec2(0, 0) assert isinstance(ret, Vec2) return ret
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)
while True: # Clear everything for particle in particles: particle.density = DENSITY particle.pressure_force = Vec2(0,0) particle.viscosity_force = Vec2(0,0) # Calculate fluid density around each particle for particle in particles: for neighbor in particles: # If particles are close together, density increases distance = particle.position - neighbor.position # A vector if length(distance) <= H: # Particles are close enough to matter particle.density += MASS * W(distance, H) # Calculate forces on each particle based on density for particle in particles: for neighbor in particles: distance = particle.position - neighbor.position if length(distance) <= H: # Temporary terms used to caclulate forces density_p = particle.density density_n = neighbor.density assert(density_n != 0) # Dividing by density later # Pressure derived from the ideal gas law (constant temp) pressure_p = k * (density_p - DENSITY)
while True: # Clear everything for particle in particles: particle.density = DENSITY particle.pressure_force = Vec2(0, 0) particle.viscosity_force = Vec2(0, 0) # Calculate fluid density around each particle for particle in particles: for neighbor in particles: # If particles are close together, density increases distance = particle.position - neighbor.position # A vector if length(distance) <= H: # Particles are close enough to matter particle.density += MASS * W(distance, H) # Calculate forces on each particle based on density for particle in particles: for neighbor in particles: distance = particle.position - neighbor.position if length(distance) <= H: # Temporary terms used to caclulate forces density_p = particle.density density_n = neighbor.density assert (density_n != 0) # Dividing by density later # Pressure derived from the ideal gas law (constant temp) pressure_p = k * (density_p - DENSITY)