#!/usr/bin/perl $pi = 3.14159265359; # An eagle "wire" specifies two endpoints, and an optional curvature. # A curvature requires we calculate a centerpoint for a circle. # A curvature of zero is implemented as a simple hull around the endpoints. sub wire { local($x1, $y1, $x2, $y2, $curve, $width) = @_; $curve = 0 unless defined $curve; $curve *= $pi / 180; # Convert to radians $width = 0.1 unless $width; if ($curve == 0) { print "hull() {\n"; print " translate([$x1, $y1, 0]) circle(d=$width);\n"; print " translate([$x2, $y2, 0]) circle(d=$width);\n"; print "}\n\n"; } else { # Some trig to establish the center. # Compute the length of the chord. $dist = sqrt(($y2-$y1)*($y2-$y1) + ($x2-$x1)*($x2-$x1)); # Based on the given curve, project on the unit circle. # One endpoint of the resultant chord is [1, 0]. # Find the other endpoint. $atan = atan2(($y2-$y1), ($x2-$x1)); $cos = cos($curve); $sin = sin($curve); # Now, what is the length of the chord on the unit circle? $udist = sqrt(($sin*$sin) + ($cos-1)*($cos-1)); # Their ratio is the desired radius. # (r should be 9.525 in the example.) $r = $dist / $udist; #print "r = $r\n"; # At this point, $atan has the angle from [x1, y1] to [x2, y2]. # To that, we must add (180-abs($curve))/2 to point to the center. # Note that the sign of $curve and of our addend should be the same. # Now, get the rise and run of the angle formed by the chord # and a line from [x1, y2] to the center point. $a = ($pi - abs($curve)) / 2; $a = -$a if $curve < 0; $a += $atan; $rise = sin($a) * $r; $run = cos($a) * $r; #print "run, rise = ", cos($a), " ", sin($a), "\n"; # BUGBUG: $rise and $run must be sign adjusted for quadrant! # Calculate the center point for the arc. #print "[x1, y1] + [run, rise] == [$x1, $y1] + [$run, $rise]\n"; $x = $x1 + $run; $y = $y1 + $rise; #print "center: [$x, $y]\n\n"; # We finally know the radius and center of the arc # so we can render it. Start with the endpoints. print "translate([$x1, $y1, 0]) circle(d=$width);\n"; print "translate([$x2, $y2, 0]) circle(d=$width);\n"; # Render the outer circle, then subtract the inner circle # and the masking polygon. print "difference() {\n"; print " translate([$x, $y, 0]) circle(r=$r+$width/2);\n"; print " translate([$x, $y, 0]) circle(r=$r-$width/2);\n"; # Compute corners for a masking rectangle. # We still have $angle, but compute the center of the chord. $x = ($x2+$x1) / 2; $y = ($y2+$y1) / 2; # Now construct a polygon by going $r away from the center of # the chord on either side, then 2*$r at right angles. # TODO: Masking polygon $rise = sin($atan) * $r; $run = cos($atan) * $r; $x1 = $x - $width - $run; $y1 = $y - $width - $rise; $x2 = $x + $width + $run; $y2 = $y + $width + $rise; # Make an appropriate right angle. $a = $atan - $pi/2; $a = $atan + $pi/2 if $curve < 0; # And a slope for the new sides. $rise = sin($a) * $r; $run = cos($a) * $r; $x3 = $x2 - 2*$run; $y3 = $y2 - 2*$rise; $x4 = $x1 - 2*$run; $y4 = $y1 - 2*$rise; print " polygon(points=[[$x1, $y1], [$x2, $y2], [$x3, $y3], [$x4, $y4]]);\n"; print "}\n\n"; } } # # Read the .brd and output the OpenSCAD. # open(INPUT, "8ipanel.brd") || die "8ipanel.brd: $!"; print "\$fn=24;\n"; print "linear_extrude(height=0.1) {\n"; while () { if (//) { /x1="([^"]*)"/ || die; $x1 = $1; /y1="([^"]*)"/ || die; $y1 = $1; /x2="([^"]*)"/ || die; $x2 = $1; /y2="([^"]*)"/ || die; $y2 = $1; /width="([^"]*)"/ || die; $width = $1; # next if $width == 0; /layer="([^"]*)"/ || die; $layer = $1; $curve = 0; $curve = $1 if /curve="([^"]*)"/; # Call a subroutine for the hard work. &wire($x1, $y1, $x2, $y2, $curve, $width); } elsif (//) { /x="([^"]*)"/ || die; $x = $1; /y="([^"]*)"/ || die; $y = $1; /radius="([^"]*)"/ || die; $radius = $1; /width="([^"]*)"/ || die; $width = $1; /layer="([^"]*)"/ || die; $layer = $1; # Draw the circle with radius $radius+($width/2). # Subtract the circle with radius $radius-($width/2). print "translate ([$x, $y, 0])\n"; print "difference() {\n"; print " circle(r=$radius+$width/2);\n"; print " circle(r=$radius-$width/2);\n}\n"; } } print "}\n";