def test_translate(self): offset_x = 5 offset_y = 11 offset_coord = Coordinate(5, 11) coords = [ Coordinate(0.0, 0.0), Coordinate(0.4, 0.3), Coordinate(0.8, 0.6), Coordinate(1.2, 0.9), ] s1 = Surface(coords) s2 = Surface.translate(s1, offset_coord) for i in range(len(s2.coordinates)): orig_coord = coords[i] surface_coord = s2.coordinates[i] assert orig_coord.x + offset_x == surface_coord.x assert orig_coord.y + offset_y == surface_coord.y #test offset with invalid object with pytest.raises(TypeError): Surface.translate(s2, 1) # try using +/- operators s3 = s1 + offset_coord assert s2 == s3 s4 = s3 - offset_coord assert s1 == s4
def test_coordinate_example(self): from hotwing_core import Coordinate c1 = Coordinate(0, 0) c2 = Coordinate(0.25, 0.2) c3 = Coordinate(0.5, 0.25) # you can add, subtract and multiply Coordinates c4 = c2 + c3 # 0.75,0.45
def test_interpolate_new_surface(self): coords = [ Coordinate(0.0, 0.0), Coordinate(0.4, 0.2), Coordinate(0.8, 0.4), Coordinate(1.2, 0.6), ] # make same surface s1 = Surface(coords) s2 = Surface(coords) length = 500 s3 = Surface.interpolate_new_surface(s1, s2, 10, 3, length) assert len(s3.coordinates) == length # test each original coordinate to see if it's the same # doesn't validate correctly on an interpolated foil but # works on our linear example for c in s1.coordinates: assert c == s3.interpolate(c.x) # also only works on our contrived example for i in range(len(s1.coordinates) - 1): c1 = coords[i] c2 = coords[i + 1] c3 = c1 + c2 c3 = c3 * 0.5 assert s1.interpolate(c3.x) == s3.interpolate(c3.x)
def test_interpolate(self): # Straignt line x=y coords = [ Coordinate(0.0, 0.0), Coordinate(0.4, 0.4), Coordinate(0.8, 0.8), Coordinate(1.2, 1.2), ] s = Surface(coords) for i in range(100): val = i / 100.0 result = s.interpolate(val) assert result == Coordinate(val, val) # horizontal line y=0.5 coords = [ Coordinate(0.0, 0.5), Coordinate(0.4, 0.5), Coordinate(0.8, 0.5), Coordinate(1.2, 0.5), ] s = Surface(coords) for i in range(100): val = i / 100.0 result = s.interpolate(val) assert result == Coordinate(val, 0.5)
def test_subtract(self): c1 = Coordinate(1, 2) c2 = Coordinate(3, 4) e = Coordinate(1 - 3, 2 - 4) assert c1 - c2 == e with pytest.raises(NotImplementedError): c1 - 1
def test_add(self): c1 = Coordinate(1, 2) c2 = Coordinate(3, 4) e = Coordinate(1 + 3, 2 + 4) assert c1 + c2 == e with pytest.raises(NotImplementedError): c1 + 1
def test_add_sub(self): top = [ Coordinate(0.2, 0.4), Coordinate(0.4, 0.5), Coordinate(0.6, 0.6), Coordinate(0.8, 0.7) ] bottom = [ Coordinate(0.3, 0.1), Coordinate(0.4, 0.2), Coordinate(0.5, 0.3), Coordinate(0.6, 0.4) ] coord = Coordinate(1, 2) p1 = Profile(top + bottom) p2 = p1 + coord p3 = p2 - coord assert p1 == p3 with pytest.raises(NotImplementedError): p1 + 1 with pytest.raises(NotImplementedError): p1 - "s"
def test_offset(self): ## test for 0 slope coords = [ Coordinate(0.2, 0.0), Coordinate(0.4, 0.0), Coordinate(0.6, 0.0), Coordinate(1.2, 0.6), ] s1 = Surface(coords) offset = 1.125 s2 = Surface.offset_around_surface(s1, offset)
def test_equality(self): coords1 = [ Coordinate(0.0, 0.0), Coordinate(0.4, 0.4), Coordinate(0.8, 0.8), Coordinate(1.2, 1.2), ] coords2 = [ Coordinate(0.0, 0.0), Coordinate(0.5, 0.1), Coordinate(0.8, 0.8), Coordinate(1.2, 1.2), ] s1 = Surface(coordinates) s2 = Surface(coordinates_no_dupe) s3 = Surface(short_surface) # same length different coords s4 = Surface(coords1) s5 = Surface(coords2) assert s1 == s2 assert s1 != s3 assert not s1 == s3 assert not s4 == s5 with pytest.raises(NotImplementedError): s1 == 1 with pytest.raises(NotImplementedError): s2 != "s"
def test_trim(self): top = [ Coordinate(0.2, 0.4), Coordinate(0.4, 0.5), Coordinate(0.6, 0.6), Coordinate(0.8, 0.7) ] bottom = [ Coordinate(0.3, 0.1), Coordinate(0.4, 0.2), Coordinate(0.5, 0.3), Coordinate(0.6, 0.4) ] # trim using the min and max x - should not change p1 = Profile(top + bottom) p2 = Profile.trim(p1, 0.2, 0.8) assert p1.top == p2.top # extend profile p3 = Profile.trim(p1, 0, 1) assert p3.x_bounds[0] == 0 assert p3.x_bounds[1] == 1 # Try Using None Values p4 = Profile.trim(p1, None, 1) assert p4.x_bounds[0] == 0.2 assert p4.x_bounds[1] == 1 p5 = Profile.trim(p1, 0, None) assert p5.x_bounds[0] == 0 assert p5.x_bounds[1] == 0.8 p6 = Profile.trim(p1, None, None) assert p6.x_bounds[0] == 0.2 assert p6.x_bounds[1] == 0.8
def final_example(self): from hotwing_core import Profile from hotwing_core import Rib from hotwing_core import Machine from hotwing_core import Panel from hotwing_core import Coordinate ## Setup Rib r1 = Rib( "http://airfoiltools.com/airfoil/seligdatfile?airfoil=s6063-il", scale=10, xy_offset=None, top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) r2 = Rib( "http://airfoiltools.com/airfoil/seligdatfile?airfoil=rg14-il", scale=10, xy_offset=Coordinate(0, 0), top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) # Setup Panel p = Panel(r1, r2, 24) # Trim Panel p1 = Panel.trim(p, 0, 12) # Setup Machine m = Machine(24, kerf=0.075, profile_points=200) # Load panel into machine m.load_panel(panel=p1, left_offset=6) # Generate GCode gcode = m.generate_gcode(safe_height=5)
def test_create_machine(self): from hotwing_core import Coordinate from hotwing_core import Profile from hotwing_core import Rib from hotwing_core import Panel ## Create Root Rib r1 = Rib( "http://airfoiltools.com/airfoil/seligdatfile?airfoil=s6063-il", scale=10, xy_offset=None, top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) ## Create Tip Rib r2 = Rib( "http://airfoiltools.com/airfoil/seligdatfile?airfoil=rg14-il", scale=10, xy_offset=Coordinate(0, 0), top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) # Setup Panel - takes the two ribs, at a specified distance of 24 units (inches or centimeters) p = Panel(r1, r2, 24) # A Panel can be trimmed. Say for example, the machine you will be using to cut your wing will # only cut wings up to 12 units. We can use the Panel.trim classmethod to create a new, # Panel. The trim will handle the interpolation and creation of a new Rib and Panel. p1 = Panel.trim( p, 0, 12 ) # cut at 0 (no cut will occur) and at 12 - new panel is 12 units long. p2 = Panel.trim( p, 12, 24 ) # cut at 12 and at 24 (no cut will occur) - new panel is 12 units long. from hotwing_core import Machine # Setup Machine m = Machine( 24, # Width between pillars of machine kerf=0.075, # Allowance for wire size and melted foam profile_points= 200, # number of points to use for each surface when iterpolating ) # Load panel into machine (p1 is the panel created in the previous step) # The offset is the distance the left of the panel will be from the left of the machine -- # If you want it centered, for this example use an offset of 6 -- # (24-12[machine width-panel width]) -> 12/2(equal amount on each side) m.load_panel(panel=p1, left_offset=6) # Generate GCode # safe_height is where the machine can move without hitting anything gcode = m.generate_gcode(safe_height=5)
def test_rotate(self): coords = [ Coordinate(0.0, 0.0), Coordinate(0.4, 0.2), Coordinate(0.8, 0.4), Coordinate(1.2, 0.6), ] s = Surface(coords) o = Coordinate(0, 0) a = 90 r = Surface.rotate(o, s, a) r.coordinates[0] == Coordinate(0, 0) r.coordinates[1] == Coordinate(-0.2, 0.4) r.coordinates[2] == Coordinate(-0.8, -0.4), r.coordinates[3] == Coordinate(0.6, -1.2)
def test_calc_slope(self): c1 = Coordinate(0, 0) c2 = Coordinate(1, 1) s1 = Coordinate.calc_slope(c1, c2) assert s1 == 1 c1 = Coordinate(0, 0) c2 = Coordinate(1, 0) s1 = Coordinate.calc_slope(c1, c2) assert s1 == 0 # test infinite slope c1 = Coordinate(0, 0) c2 = Coordinate(0, 0) s1 = Coordinate.calc_slope(c1, c2) assert s1 >= 1000000
def test_scale(self): coords = [ Coordinate(0.0, 0.1), Coordinate(0.4, 0.2), Coordinate(0.8, 0.4), Coordinate(1.2, 0.6), ] scale = 5 s = Surface(coords) s1 = Surface.scale(s, scale) s2 = s * 5 # scaling by method or multiplying should yield same values for i in range(len(s.coordinates)): assert s1.coordinates[i] == s2.coordinates[i] # validate coordinates scaled correctly for i in range(len(s.coordinates)): c_x = coords[i].x c_y = coords[i].y s1.coordinates[i] == Coordinate(c_x * scale, c_y * scale)
def test_equality_comparison(self): x = 1 y = 1.4 c1 = Coordinate(x, y) c2 = Coordinate(x, y) c3 = Coordinate(y, x) assert c1 == c2 assert not c2 == c3 # test inequality operator too assert c2 != c3 assert not c1 != c2 # try comparison to non object with pytest.raises(NotImplementedError): 1 == c1 with pytest.raises(NotImplementedError): c1 == 1 with pytest.raises(NotImplementedError): 1 != c1 with pytest.raises(NotImplementedError): c1 != 1
def test_rotate(self): top = [ Coordinate(0.2, 0.4), Coordinate(0.4, 0.5), Coordinate(0.6, 0.6), Coordinate(0.8, 0.7) ] bottom = [ Coordinate(0.3, 0.1), Coordinate(0.4, 0.2), Coordinate(0.5, 0.3), Coordinate(0.6, 0.4) ] p1 = Profile(top + bottom) origin = Coordinate(1, 2) angle = 10 p1_r = Profile.rotate(origin, p1, angle) p2 = Profile.rotate(origin, p1_r, -angle) assert p1 == p2
def test_cutting_strategies(self): from hotwing_core import Profile from hotwing_core import Rib from hotwing_core import Machine from hotwing_core import Panel from hotwing_core import Coordinate ## Setup Rib r1 = Rib("http://m-selig.ae.illinois.edu/ads/coord/ah83159.dat", scale=10, xy_offset=None, top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25 ) r2 = Rib("http://m-selig.ae.illinois.edu/ads/coord/rg14.dat", scale=10, xy_offset=Coordinate(0, 0), top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25 ) # Setup Panel p = Panel(r1, r2, 24) cutting_strategy_names=["CuttingStrategy1","CuttingStrategy2"] for csn in cutting_strategy_names: # Setup Machine m = Machine(24, kerf=0.075, units="inches", cutting_strategy_name=csn, profile_points=300) # Load panel into machine m.load_panel(p) # Generate GCode gcode = m.generate_gcode(safe_height=3) # test default m = Machine(24, kerf=0.075, units="inches", cutting_strategy_name="default", profile_points=300) # Load panel into machine m.load_panel(p) # Generate GCode gcode = m.generate_gcode(safe_height=3) # test invalid m = Machine(24, kerf=0.075, units="inches", cutting_strategy_name="bad name", profile_points=300) # Load panel into machine m.load_panel(p) # Generate GCode gcode = m.generate_gcode(safe_height=3)
def test_multiply(self): c1 = Coordinate(0, 1) c2 = Coordinate(2, 3) assert c1 * c2 == Coordinate(0 * 2, 1 * 3) # test with numeric objects assert c1 * 2 == Coordinate(0 * 2, 1 * 2) assert c1 * 2 == Coordinate(0 * float(2), 1 * float(2)) assert c1 * 2 == Coordinate(0 * Decimal(2), 1 * Decimal(2))
def test_left_right_bounds(self): coords = [ Coordinate(0.6, 0), Coordinate(0.4, 0.2), Coordinate(0.2, 0.3), Coordinate(0.1, 0.1) ] s = Surface(coords) assert s.right == coords[0] assert s.left == coords[-1] assert s.bounds == (Coordinate(0.1, 0), Coordinate(0.6, 0.3)) # reverse coords and try again s = Surface(list(reversed(coords))) assert s.right == coords[0] assert s.left == coords[-1] assert s.bounds == (Coordinate(0.1, 0), Coordinate(0.6, 0.3))
def test_translate(self): top = [ Coordinate(0.2, 0.4), Coordinate(0.4, 0.5), Coordinate(0.6, 0.6), Coordinate(0.8, 0.7) ] bottom = [ Coordinate(0.3, 0.1), Coordinate(0.4, 0.2), Coordinate(0.5, 0.3), Coordinate(0.6, 0.4) ] # trim using the min and max x - should not change p1 = Profile(top + bottom) offset = Coordinate(1, 2) p2 = Profile.translate(p1, offset) for i in range(len(p1.top.coordinates)): assert p2.top.coordinates[i] == p1.top.coordinates[i] + offset p3 = p1 + offset assert p2 == p3
def test_split(self): top = [ Coordinate(0.2, 0.3), Coordinate(0.4, 0.4), Coordinate(0.6, 0.5), Coordinate(0.8, 0.6) ] bottom = [ Coordinate(0.3, 0.2), Coordinate(0.4, 0.4), Coordinate(0.5, 0.6), Coordinate(0.6, 0.8) ] p = Profile(top + bottom) assert len(p.top.coordinates) == len(top) assert p.top == Surface(top) assert len(p.bottom.coordinates) == len(bottom) assert p.bottom == Surface(bottom)
def test_bounds(self): top = [ Coordinate(0.2, 0.4), Coordinate(0.4, 0.5), Coordinate(0.6, 0.6), Coordinate(0.8, 0.7) ] bottom = [ Coordinate(0.3, 0.1), Coordinate(0.4, 0.2), Coordinate(0.5, 0.3), Coordinate(0.6, 0.4) ] p = Profile(top + bottom) assert p.x_bounds[0] == 0.2 assert p.x_bounds[1] == 0.8 assert p.y_bounds[0] == 0.1 assert p.y_bounds[1] == 0.7
def test_gcode_formatters(self): from hotwing_core import Profile from hotwing_core import Rib from hotwing_core import Machine from hotwing_core import Panel from hotwing_core import Coordinate ## Setup Rib r1 = Rib("http://m-selig.ae.illinois.edu/ads/coord/ah83159.dat", scale=10, xy_offset=None, top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) r2 = Rib("http://m-selig.ae.illinois.edu/ads/coord/rg14.dat", scale=10, xy_offset=Coordinate(0, 0), top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) # Setup Panel p = Panel(r1, r2, 24) gcode_formatter_names = [ "GenericGcodeFormatter", "DebugGcodeFormatter", "default" ] for gfn in gcode_formatter_names: # Setup Machine m = Machine(24, kerf=0.075, units="inches", gcode_formatter_name=gfn, profile_points=300) # Load panel into machine m.load_panel(p) # Generate GCode gcode = m.generate_gcode(safe_height=3)
def test_create_panel(self): from hotwing_core import Coordinate from hotwing_core import Profile from hotwing_core import Rib from hotwing_core import Panel ## Create Root Rib r1 = Rib( "http://airfoiltools.com/airfoil/seligdatfile?airfoil=s6063-il", scale=10, xy_offset=None, top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) ## Create Tip Rib r2 = Rib( "http://airfoiltools.com/airfoil/seligdatfile?airfoil=rg14-il", scale=10, xy_offset=Coordinate(0, 0), top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) # Setup Panel - takes the two ribs, at a specified distance of 24 units (inches or centimeters) p = Panel(r1, r2, 24) # A Panel can be trimmed. Say for example, the machine you will be using to cut your wing will # only cut wings up to 12 units. We can use the Panel.trim_panel classmethod to create a new, # Panel. The trim_panel will handle the interpolation and creation of a new Rib and Panel. p1 = Panel.trim( p, 0, 12 ) # cut at 0 (no cut will occur) and at 12 - new panel is 12 units long. p2 = Panel.trim( p, 12, 24 ) # cut at 12 and at 24 (no cut will occur) - new panel is 12 units long.
def test_create_profile(self): from hotwing_core import Coordinate from hotwing_core import Surface from hotwing_core import Profile top = [ Coordinate(1.000, 0.000), Coordinate(0.900, 0.015), Coordinate(0.800, 0.030), Coordinate(0.700, 0.045), Coordinate(0.600, 0.060), Coordinate(0.500, 0.075), Coordinate(0.400, 0.090), Coordinate(0.300, 0.105), Coordinate(0.200, 0.100), Coordinate(0.100, 0.075), Coordinate(0.000, 0.000), ] bottom = [ Coordinate(1.000, 0), Coordinate(0.900, -0.00375), Coordinate(0.800, -0.0075), Coordinate(0.700, -0.01125), Coordinate(0.600, -0.015), Coordinate(0.500, -0.01875), Coordinate(0.400, -0.0225), Coordinate(0.300, -0.02625), Coordinate(0.200, -0.025), Coordinate(0.100, -0.01875), Coordinate(0.000, 0), ] both = top + bottom # You can create a profile from a list of Coordinates p = Profile(both) # You can create a Coordinate from two - top and bottom - Surface objects. p = Profile(Surface(top), Surface(bottom)) # You can open an airfoil from dat (Selig or Lednicer format) a file on your hard drive # p = Profile("profiles/myprofile.dat") # You can open an airfoil from dat (Selig or Lednicer format) via a URL: p = Profile("http://m-selig.ae.illinois.edu/ads/coord/e374.dat")
def test_surface_example(self): from hotwing_core import Coordinate from hotwing_core import Surface # A list of coordinates that will make up a Surface coords = [ Coordinate(1.000, 0.000), Coordinate(0.900, 0.015), Coordinate(0.800, 0.030), Coordinate(0.700, 0.045), Coordinate(0.600, 0.060), Coordinate(0.500, 0.075), Coordinate(0.400, 0.090), Coordinate(0.300, 0.105), Coordinate(0.200, 0.100), Coordinate(0.100, 0.075), Coordinate(0.000, 0.000) ] s = Surface(coords)
from hotwing_core import Machine from hotwing_core import Panel from hotwing_core import Coordinate ## Setup Rib r1 = Rib("http://m-selig.ae.illinois.edu/ads/coord/ah83159.dat", scale=10, xy_offset=None, top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) r2 = Rib("http://m-selig.ae.illinois.edu/ads/coord/rg14.dat", scale=10, xy_offset=Coordinate(0, 0), top_sheet=0.0625, bottom_sheet=0.0625, front_stock=0.5, tail_stock=1.25) # Setup Panel p = Panel(r1, r2, 24) # Trim Panel p = Panel.trim(p, 0, 12) # Setup Machine m = Machine(24, kerf=0.075, units="inches", profile_points=300) # Load panel into machine
import sys, os import pytest myPath = os.path.dirname(os.path.abspath(__file__)) sys.path.insert(0, myPath + '/../') from hotwing_core import Coordinate, Surface coordinates = [ Coordinate(1, 0), Coordinate(1, 0), # Dupe Coordinate(0.99667, 0.00045), Coordinate(0.98707, 0.00195), Coordinate(0.97194, 0.00446), Coordinate(0.95169, 0.0076), Coordinate(0.92645, 0.01112), Coordinate(0.89647, 0.01506), Coordinate(0.86218, 0.01937), Coordinate(0.82405, 0.02394), Coordinate(0.78255, 0.02867), Coordinate(0.73817, 0.03344), Coordinate(0.6914499, 0.03811), Coordinate(0.6914499, 0.03811), # Dupe Coordinate(0.6914499, 0.03811), # Dupe Coordinate(0.64292, 0.04256), Coordinate(0.5931, 0.04666), Coordinate(0.54254, 0.05029), Coordinate(0.49178, 0.05334), Coordinate(0.44133, 0.0557), Coordinate(0.39172, 0.05727), Coordinate(0.34343, 0.058), Coordinate(0.29692, 0.0578),
def test_length(self): coords = [ Coordinate(0.1, 0), Coordinate(0.3, 0), Coordinate(0.7, 0), Coordinate(0.9, 0) ] s = Surface(coords) assert s.length == 0.8 coords = [ Coordinate(0, 0.1), Coordinate(0, 0.3), Coordinate(0, 0.7), Coordinate(0, 0.9) ] s = Surface(coords) assert s.length == 0.8 coords = [ Coordinate(0.0, 0.0), Coordinate(0.4, 0.3), Coordinate(0.8, 0.6), Coordinate(1.2, 0.9), ] s = Surface(coords) assert s.length == 3 * 0.5