def fit_line(x, y, imin: int = 0, imax: int = -1): """ """ x = x[imin:imax + 1] y = y[imin:imax + 1] print(x, y) f = lambda x, m, q: m * x + q popt, pcov = curve_fit(f, x, y) print(popt) line = Line(Point(x[0], f(x[0], *popt)), Point(x[-1], f(x[-1], *popt))) print(line) return line
def construct(self): """ """ hw = 0.5 * self.width hh = 0.5 * self.height p = Point(-hw, hh) top = Line(p, p.move(self.width, 0.)) c = top.end_point.move(hh, -90.) right = CircularArc(c, hh, 90., -180.) bot = right.connecting_line(self.width) left = CircularArc(c.move(self.width, 180.), hh, -90., -180.) return locals()
def construct(self): """Overloaded method. """ p1 = self.anchor + Point(-self.w + self.d, 0.5 * self.h) line1 = Line(p1, p1.hmove(self.w - self.r)) arc1 = line1.connecting_circular_arc(-self.r, -90.) line2 = arc1.connecting_line(-self.h + 2. * self.r) arc2 = line2.connecting_circular_arc(-self.r, -90.) line3 = arc2.connecting_line(-self.w + self.r) line4 = Line(line3.end_point(), p1) h1 = Hole(Point(self.d - self.hp, 0.5 * self.hs), self.hd) h2 = Hole(Point(self.d - self.hp, -0.5 * self.hs), self.hd) h3 = Hole(Point(-self.w + self.d + self.hp, 0.5 * self.hs), self.hd) h4 = Hole(Point(-self.w + self.d + self.hp, -0.5 * self.hs), self.hd) return locals()
def write_logo(width=450., height=350, dpi=100, text_size=3., line_width=2.5, margin=-0.01): """Create the logo for the package. """ body = MusicManAxis() offset = Point(-200., 0.) width, height, dpi = setup_page((width, height), dpi, text_size, line_width) plt.figure('metalute logo') plt.gca().set_aspect('equal') hmargin = margin vmargin = hmargin * width / height plt.subplots_adjust(left=hmargin, right=1. - hmargin, top=1. - vmargin, bottom=vmargin) plt.xticks([]) plt.yticks([]) w = 0.5 * width * (1. - 2. * hmargin) h = 0.5 * height * (1. - 2. * vmargin) plt.gca().axis([-w, w, -h, h]) body.draw(offset) kwargs = dict(ha='center', va='center', family='DejaVu Sans Mono') plt.text(-75., 40., 'M', **kwargs, size=450) plt.text(20., 18., 'eta', **kwargs, size=150, color='orange') plt.text(-51., -50., 'L', **kwargs, size=450) plt.text(-8., -55., 'ute', **kwargs, size=150, color='orange') plt.tight_layout(pad=-1.) file_path = os.path.join(METALUTE_DOCS, '_static', 'metalute_logo.png') plt.savefig(file_path)
def dim(p1, p2, offset, padding: float = 2., distance: float = 15., margin: float = 5.): """ """ p1 += offset p2 += offset fmt = dict(offset=Point(0., 0.), color='lightgray') # Basic setup. line = Line(p1, p2) phi = line.slope() - 90. length = line.length() d = distance + margin # Draw the two lines from the original points defining the dimension. Line(p1.move(padding, phi), p1.move(d, phi)).draw(**fmt) Line(p2.move(padding, phi), p2.move(d, phi)).draw(**fmt) # Now the actual dimension. _p1 = p1.move(distance, phi) _p2 = p2.move(distance, phi) l = Line(_p1, _p2) m = l.midpoint() text = '{:.2f}'.format(length) rot = phi + 90. if rot < -90.: rot += 180. elif rot > 90: rot -= 180 print(rot) plt.text(*m.xy(), text, rotation=rot, ha='center', va='center') _d = 1.2 * len(text) Arrow(m.move(_d, phi - 90.), _p1).draw(**fmt) Arrow(m.move(_d, phi + 90.), _p2).draw(**fmt)
def fit_circle_arc(x, y, imin: int = 0, imax: int = -1, invert: bool = False): """ """ x = x[imin:imax + 1] y = y[imin:imax + 1] barycenter = np.mean(x), np.mean(y) center, _ = leastsq(circle_residuals, barycenter, args=(x, y)) radius = distance_from_center(x, y, *center).mean() center = Point(*center) phi1 = Line(center, Point(x[0], y[0])).slope() phi2 = Line(center, Point(x[-1], y[-1])).slope() if invert: phi1, phi2 = phi2, phi1 arc = CircularArc(center, radius, phi1, phi2 - phi1) print(arc) return arc
def test_poly_path(self): """ """ blueprint('Test ParametricPolyPath', 'A4') offset = Point(0., 0.) class Pillow(ParametricPolyPathBase): DEFAULT_PAR_DICT = dict(width=75., height=25.) def construct(self): """ """ hw = 0.5 * self.width hh = 0.5 * self.height p = Point(-hw, hh) top = Line(p, p.move(self.width, 0.)) c = top.end_point.move(hh, -90.) right = CircularArc(c, hh, 90., -180.) bot = right.connecting_line(self.width) left = CircularArc(c.move(self.width, 180.), hh, -90., -180.) return locals() p = Pillow() p.draw_construction(offset) p.draw(offset) p.draw_reference_points(offset)
def draw(self, offset): """Overloaded method. """ self._draw_contour(self.inner_length, self.inner_width, offset) self._draw_contour(self.inner_length, self.outer_width, offset) if self.outer_length != self.inner_length: w = 0.5 * self.inner_width - 0.25 * self.inner_length d = 6. p1 = Point(-0.5 * self.inner_length, w) p2 = Point(p1.x - self.outer_length + self.inner_length, d) p3 = p2.vmove(-2. * d) p4 = Point(-0.5 * self.inner_length, -w) Line(p1, p2).draw(offset) Line(p2, p3).draw(offset) Line(p3, p4).draw(offset) self.draw_magnets(offset) self.draw_screw_holes(offset)
def test_head_accuracy(self): """ """ blueprint('Music Man Axis head accuracy', 'A4') offset = Point(-60., 0.) plt.plot(self.xh + offset.x, self.yh + offset.y, 'o') head = Head() head.draw_top(offset)
def test_body_accuracy(self): """ """ blueprint('Music Man Axis body accuracy', 'A1') offset = Point(-200., -50.) plt.plot(self.xb + offset.x, self.yb + offset.y, 'o') body = Body() body.draw(offset)
def draw(self, offset, **kwargs): """Overloaded method. """ super().draw(offset) self.routing.draw(offset, **kwargs) p = Point(-0.5 * self.LENGTH + self.BORDER, -0.5 * self.WIDTH + self.BORDER) self.routing.draw_parameters(offset + p)
def place_holes(self): """ """ hole_distance_to_edge = 12.634 string_pitch = 6.7 g_string_offset = -1.45 slope = self.contour.path('line3').slope() arc = self.contour.path('arc2') pivot = arc.end_point().move(hole_distance_to_edge, arc.end_phi) scale = 1. / abs(np.sin(np.radians(slope))) pitch = string_pitch * scale delta = (pivot.y + g_string_offset) * scale - 3. * pitch for i in range(4): self.add_hole(pivot.move(i * pitch + delta, slope)) # This is horrible, as the last points are added by hand. self.add_hole(Point(76.75, -13.35)) self.add_hole(Point(52.05, -20.02))
def vdim(p1, p2, offset, padding: float = 2., distance: float = 15., margin: float = 5.): """ """ fmt = dict(color='lightgray') xmax = max(p1.x, p2.x) _p1 = Point(xmax, p1.y) _p2 = Point(xmax, p2.y) if p1.x > p2.x: Line(p2, _p2).draw(offset + Point(padding, 0.), **fmt) else: Line(p1, _p1).draw(offset + Point(padding, 0.), **fmt) dim(_p1, _p2, offset, padding, distance, margin)
def test_head_draw(self): """ """ blueprint('Music Man Axis head', 'A4') offset = Point(-60., 0.) head = Head() head.contour.draw_construction(offset) head.draw_top(offset) head.contour.draw_reference_points(offset)
def test_accuracy(self): """ """ blueprint('Fender Stratocaster accuracy', 'A4') x, y, xh, yh = self.load_data() offset = Point(-80., 0.) plt.plot(x + offset.x, y + offset.y, 'o') head = FenderStratocasterContour() head.draw(offset)
def test_body_draw(self): """ """ blueprint('Music Man Axis', 'A1') offset = Point(-200., -50.) body = Body() body.draw_construction(offset) body.draw(offset) body.draw_reference_points(offset)
def test_draw(self): """ """ blueprint('Fender Stratocaster', 'A4') offset = Point(-80., 0.) head = FenderStratocaster() head.contour.draw_construction(offset) head.draw_top(offset) head.dimension_top(offset) head.contour.draw_reference_points(offset)
def test(self): """ """ offset = Point(-80., 0.) blueprint('Bliss---cool, eh?', 'A4') head = BlissContour() head.draw_construction(offset) head.draw(offset) head.draw_reference_points(offset) MusicManContour().draw(offset, color='lightgray') blueprint('Bliss simplified', 'A4') head.draw(offset)
def test_circular_arc(self) -> None: """Test the circular arc class. """ blueprint('Test CircularArc', 'A4') offset = Point(0., 0.) c1 = Point(0., 0., 'c1') arc1 = self._test_circular_arc_base(c1, 20., 0., 90., offset) c2 = Point(40., 40., 'c2') arc2 = self._test_circular_arc_base(c2, 30, 0., -90., offset, color='red') c3 = Point(-40., -40., 'c3') arc3 = self._test_circular_arc_base(c3, 25, 250., 40., offset, color='blue') c4 = Point(-40., 40., 'c4') arc4 = self._test_circular_arc_base(c4, 15, 180., -90., offset)
def draw(self, offset): """Overloaded method. """ l = 0.5 * self.inner_length w = self.inner_width d = Point(0.5 * l, 0.) SingleCoilBase._draw_contour(l, w, offset - d) self.draw_magnets(offset - d) SingleCoilBase._draw_contour(l, w, offset + d) self.draw_magnets(offset + d) self.draw_screw_holes(offset) RoundedRectangle((0., 0.), self.inner_length, self.inner_width, self.corner_radius).draw(offset) self.draw_wings(offset)
def test_body_draw_split(self): """ """ x0 = 200. y0 = 0. blueprint('Music Man Axis 1', 'A3', orientation='Portrait') offset = Point(-100., 15.) plt.hlines(y0, -1000., 1000.) plt.vlines(x0 + offset.x, -1000., 1000.) body = Body() body.draw_construction(offset) body.draw(offset) body.draw_reference_points(offset) plt.savefig('axis1.pdf') blueprint('Music Man Axis 2', 'A3', orientation='Portrait') offset = Point(-300., 15.) plt.hlines(y0, -1000., 1000.) plt.vlines(x0 + offset.x, -1000., 1000.) body = Body() body.draw_construction(offset) body.draw(offset) body.draw_reference_points(offset) plt.savefig('axis2.pdf')
def test_draw(offset): """ """ blueprint(f'EJ #1{offset}', 'A3', orientation='Portrait') #body = Body() #body.draw(offset) x = np.array([ 0., 15., 50., 125., 200., 230., 250., 280., 300., 325., 350., 370., 385., 400., 405., 395., 384., 380.5, 379., 383., 393., 375., 354., 340., 320., 305., 298.7, 315., 334.7, 325.8, 310., 266., 230., 200., 120., 50., 10. ]) y = np.array([ 0., 80., 131., 160., 141.5, 124.3, 113.3, 106.4, 107.4, 115., 123., 125.7, 123., 110.3, 90., 68., 57., 50., 42., 28., 10., -13.2, -27.5, -28.58, -30.5, -40.5, -60., -90, -108.7, -122.5, -127.4, -115.1, -116.2, -136., -159.4, -131., -69. ]) s = ParametricSpline(x, y) s.draw(offset) #s.draw_points(offset) #scale = 1.05 #s1 = ParametricSpline(x * scale, y * scale) #s1.draw(offset - Point(8., 0.)) h1 = 52. h2 = 25. w1 = 75. x, y = s.calculate_contour(offset, tmin=0., tmax=0.5) mask = abs(y - offset.y) > h1 x = x[mask] y = y[mask] plt.plot(x, y, color='black') plt.hlines(h1 + offset.y, x[0], x[-1]) x, y = s.calculate_contour(offset, tmin=0.5, tmax=1.) mask = np.logical_and(abs(y - offset.y) > h1, x - offset.x < 317.) x = x[mask] y = y[mask] plt.plot(x, y, color='black') plt.hlines(-h1 + offset.y, x[0], x[-1]) p0 = Point(-50., 0.) l = Line(p0, p0.move(500., 0.)) l.draw(offset) p1 = Point(200., -200.) l = Line(p1, p1.vmove(400.)) l.draw(offset)
def draw(self, offset): """ """ radius = 0.5 * self.inner_length a = self.outer_length - self.inner_length b = 0.5 * (self.width - self.flat_width) - radius theta = (-b + np.sqrt(b**2. + 2 * a * radius)) / radius l = np.sqrt((a + 0.5 * radius * theta**2.)**2. + (b + radius * theta)**2.) p = Point(0., 0.5 * self.width - radius) line = CircularArc(p, radius, 0., 180. - np.degrees(theta)).draw(offset).\ connecting_line(l).draw(offset) p = line.end_point() Line(p, p.vmove(-self.flat_width)).draw(offset) p = Point(0., -0.5 * self.width + radius) line = CircularArc(p, radius, 0., -180. + np.degrees(theta)).draw(offset).\ connecting_line(l).draw(offset) p = p.hmove(0.5 * self.inner_length) Line(p, p.vmove(self.width - 2. * radius)).draw(offset)
class RoutingTemplateBase: """Base class for a routing template. This is essentially a rectangle with the center lines and some reference holes. Note this class should not be instantiated. """ LENGTH = None WIDTH = None CENTER = Point(0., 0.) BORDER = 10. def draw(self, offset): """Fundamental draw method. """ # The big rectangle. l = 0.5 * self.LENGTH w = 0.5 * self.WIDTH Rectangle(self.CENTER, self.LENGTH, self.WIDTH).draw(offset) # The two center lines. plt.hlines(0, -l, l) plt.vlines(0, -w, w) # Small centering holes. r = 1.5 Hole(self.CENTER.vmove(w), r).draw(offset) Hole(self.CENTER.vmove(-w), r).draw(offset) Hole(self.CENTER.hmove(l), r).draw(offset) Hole(self.CENTER.hmove(-l), r).draw(offset) # Bigger centering holes. r = 3. Hole(self.CENTER.vmove(w - self.BORDER), r).draw(offset) Hole(self.CENTER.vmove(-w + self.BORDER), r).draw(offset) Hole(self.CENTER.hmove(l - self.BORDER), r).draw(offset) Hole(self.CENTER.hmove(-l + self.BORDER), r).draw(offset) # And, finally, the branding :-) x = -l + self.BORDER + offset.x y = w - 2. * self.BORDER + offset.y plt.text(x, y, GITHUB_URL)
def construct(self): """Overloaded method. """ p1 = self.anchor.vmove(0.5 * self.width_at_nut) p2 = p1.hmove(self.d1) line1 = Line(p1, p2) arc1 = line1.connecting_circular_arc(self.r1, self.span1) arc2 = arc1.connecting_circular_arc(-self.r2, self.span2) line2 = arc2.connecting_line(self.d2) arc3 = line2.connecting_circular_arc(-self.r3, -self.span3) arc4 = arc3.connecting_circular_arc(self.r4, -self.span4) arc5 = arc4.connecting_circular_arc(self.r5, self.span5) arc6 = arc5.connecting_circular_arc(-self.r6, self.span6) # Last circle---here things are a little bit tricky :-) p = arc6.end_point() phi = np.degrees( np.arccos(1. - (-0.5 * self.width_at_nut - p.y) / self.r7)) dx = self.r7 * np.sin(np.radians(phi)) c7 = Point(p.x - dx, -0.5 * self.width_at_nut - self.r7) arc7 = CircularArc(c7, self.r7, 90. - phi, phi) line3 = arc7.connecting_line(arc7.end_point().x) return locals()
def draw_wings(self, offset): """Draw the hanging metal wings with the screw holes. """ w = 0.5 * (self.outer_width - self.inner_width) - self.corner_radius l = self.wing_length - 2. * self.corner_radius p = Point(0.5 * self.wing_length, 0.5 * self.inner_width) Line(p, p.vmove(w)).draw(offset).\ connecting_circular_arc(self.corner_radius, 90.).draw(offset).\ connecting_line(l).draw(offset).\ connecting_circular_arc(self.corner_radius, 90.).draw(offset).\ connecting_line(w).draw(offset) p = Point(0.5 * self.wing_length, -0.5 * self.inner_width) Line(p, p.vmove(-w)).draw(offset).\ connecting_circular_arc(-self.corner_radius, -90.).draw(offset).\ connecting_line(-l).draw(offset).\ connecting_circular_arc(-self.corner_radius, -90.).draw(offset).\ connecting_line(-w).draw(offset)
def draw(self, offset, drilling_holes=False): """Draw the routing. """ l1 = 0.5 * (self.length - self.wing_length) - self.corner_radius l2 = self.wing_length - 2. * self.corner_radius w1 = self.inner_width - 2. * self.corner_radius w2 = 0.5 * (self.outer_width - self.inner_width) - self.corner_radius p = Point(0.5 * self.wing_length, 0.5 * self.inner_width) line = self._draw_cap(p, 90., w2, l2, offset) p = line.end_point() line = self._draw_cap(p, 180., l1, w1, offset) p = line.end_point() line = self._draw_cap(p, -90., w2, l2, offset) p = line.end_point() line = self._draw_cap(p, 0., l1, w1, offset) if drilling_holes: l = self.length - 2. * self.corner_radius w = self.inner_width - 2. * self.corner_radius for p in Rectangle((0., 0.), l, w).points: Hole(p, 2 * self.corner_radius, 1.).draw(offset) l = self.wing_length - 2. * self.corner_radius w = self.outer_width - 2. * self.corner_radius for p in Rectangle((0., 0.), l, w).points: Hole(p, 2 * self.corner_radius, 1.).draw(offset)
def __test_point(self) -> None: """Test the Point class. """ p0 = Point(0., 0.) p1 = Point(1., 1., 'p1') p2 = Point(2., 2., 'p2') print(p0) print(p1) print(p2) plt.figure('Drawing points') p0.draw() p1.draw() p2.draw()
def __init__(self, **params): """Constructor. """ super().__init__(HumbuckerRouting, **params) class NeckPocketRoutingTemplate(RoutingTemplateBase): """Neck routing template. """ LENGTH = 280. WIDTH = 140. if __name__ == '__main__': offset = Point(0., 0.) blueprint('Single-coil Routing Template', 'A4', 'Luca Baldini', orientation='Portrait') SingleCoilRoutingTemplate().draw(offset) plt.savefig('single_coil_routing_template.pdf') blueprint('Humbucker Routing Template', 'A4', 'Luca Baldini', orientation='Portrait') HumbuckerRoutingTemplate().draw(offset, drilling_holes=True) plt.savefig('humbucker_routing_template.pdf')
def test_point(self) -> None: """Test the Point class. """ offset = Point(0., 0.) p1 = Point(0., 0., 'p1') p2 = Point(0., 50., 'p2') p3 = Point(-50., -50., 'p2') p4 = Point(50., 50., 'p4') p5 = Point(100., 50., 'p5') blueprint('Test dimensioning', 'A4') p1.draw(offset) p2.draw(offset) p3.draw(offset) p4.draw(offset) p5.draw(offset) dim(p1, p2, offset) dim(p1, p3, offset) dim(p3, p1, offset) dim(p4, p5, offset)