# Implementation of module {paper_figures_A} # Last edited on 2021-10-01 23:12:38 by stolfi import paper_figures_A import move import move_example import move_parms import contact import path import path_example import raster import path_hp import hacks import rn import sys from math import sqrt, hypot, sin, cos, floor, ceil, inf, nan, pi def make_figure_contour(mp, xLo,yLo, xS,yS,RS, yHi, xB0,xB1,yB,RB, xD,yD, off): # Returns the list {PCS} of contour paths for {make_figure}. See the comments in that # function for the meaning of the parameters. # PCS = [] # List of contour paths. MVS = [] # Moves of the current path. p = None # Current point of the current contour path. tag = "c" p = ( xD - off, yLo - off ) p = path.move_to(MVS, p, ( xS, yLo - off ), mp, tag) na = 12 # Number of traces in semicircle. for ia in range(na): a = pi*((ia + 1.0)/na - 0.5) q = (xS + (RS+off)*cos(a), yS + (RS+off)*sin(a)) p = path.move_to(MVS, p, q, mp, tag) p = path.move_to(MVS, p, ( xLo - off, yHi + off ), mp, tag) p = path.move_to(MVS, p, ( xLo - off, yD - off ), mp, tag) p = path.move_to(MVS, p, ( xD - off, yD - off ), mp, tag) p = path.move_to(MVS, p, ( xD - off, yLo - off ), mp, tag) path.finish(PCS, MVS, tag) # Build the contours of the two holes: for ih in range(2): tag = "b%d" % ih MVS = [] # Traces of the current contour path. p = None # Current point of the current contour path. xB = (xB0, xB1)[ih] # {X} coord of hole center. nb = 8 # Number of traces in the hole contour. for ib in range(nb + 1): b = 2*pi*(ib/nb) q = (xB + (RB-off)*cos(b), yB + (RB-off)*sin(b)) p = path.move_to(MVS, p, q, mp, tag) path.finish(PCS, MVS, tag) return PCS # ---------------------------------------------------------------------- def make_figure_filling(mp_fill, mp_jump, xLo,yLo, xS,yS,RS, yHi, xB0,xB1,yB,RB, xD,yD, wd, version): # Returns the lists {PFS} and {PLS} for {make_figure}. See the comments in that # function for the meaning of the parameters. # # Define the endpoints of the rasters: org = (xD - 2*wd, yLo - 2*wd) # Starting nozzle position. y0 = yLo + 0*wd dxS0 = 0 p00 = (xD, y0) p01 = (xS + dxS0, y0) y1 = yLo + 1*wd dxS1 = sqrt(max(0, RS**2 - (yS-y1)**2)) p10 = (xD, y1) p11 = (xS + dxS1, y1) y2 = yLo + 2*wd dxB2 = sqrt(max(0, RB**2 - (yB-y2)**2)) dxS2 = sqrt(max(0, RS**2 - (yS-y2)**2)) p20 = (xLo, y2) p21 = (xB0 - dxB2, y2) p22 = (xB0 + dxB2, y2) p23 = (xB1 - dxB2, y2) p24 = (xB1 + dxB2, y2) p25 = (xS + dxS2, y2) y3 = yLo + 3*wd dxB3 = sqrt(max(0, RB**2 - (yB-y3)**2)) dxS3 = sqrt(max(0, RS**2 - (yS-y3)**2)) p30 = (xLo, y3) p31 = (xB0 - dxB3, y3) p32 = (xB0 + dxB3, y3) p33 = (xB1 - dxB3, y3) p34 = (xB1 + dxB3, y3) p35 = (xS + dxS3, y3) y4 = yLo + 4*wd dxS4 = 0 p40 = (xLo, y4) p41 = (xS + dxS4, y4) # Joints of links near contours: ya = yLo + 0.5*wd dxSa = sqrt(max(0, RS**2 - (yS-ya)**2)) pa0 = (xS + dxSa, ya) yb = yLo + 1.5*wd dxSb = sqrt(max(0, RS**2 - (yS-yb)**2)) pb0 = (xS + dxSb, yb) yc = yLo + 2.5*wd dxBc = sqrt(max(0, RB**2 - (yB-yc)**2)) dxSc = sqrt(max(0, RS**2 - (yS-yc)**2)) pc0 = (xB0 - dxBc, yc) pc1 = (xB0 + dxBc, yc) pc2 = (xB1 - dxBc, yc) pc3 = (xB1 + dxBc, yc) pc4 = (xS + dxSc, yc) yd = yLo + 3.5*wd dxSd = sqrt(max(0, RS**2 - (yS-yd)**2)) pd0 = (xS + dxSd, yd) tag = "f" # Raster traces: mv00 = move.make(p00, p01, mp_fill); move.set_name(mv00, "T00") mv10 = move.make(p10, p11, mp_fill); move.set_name(mv10, "T10") mv20 = move.make(p20, p21, mp_fill); move.set_name(mv20, "T20") mv21 = move.make(p22, p23, mp_fill); move.set_name(mv21, "T21") mv22 = move.make(p24, p25, mp_fill); move.set_name(mv22, "T23") mv30 = move.make(p30, p31, mp_fill); move.set_name(mv30, "T30") mv31 = move.make(p32, p33, mp_fill); move.set_name(mv31, "T31") mv32 = move.make(p34, p35, mp_fill); move.set_name(mv32, "T33") mv40 = move.make(p40, p41, mp_fill); move.set_name(mv40, "T40") # Link traces: mk00 = move.make(p00, p10, mp_fill); move.set_name(mk00, "L00") mk01 = move.make(p01, pa0, mp_fill); move.set_name(mk01, "L01") mka1 = move.make(pa0, p11, mp_fill); move.set_name(mka1, "La1") mk10 = move.make(p10, p22, mp_fill); move.set_name(mk10, "L10") mk11 = move.make(p11, pb0, mp_fill); move.set_name(mk11, "L11") mkb1 = move.make(pb0, p25, mp_fill); move.set_name(mkb1, "Lb1") mk20 = move.make(p20, p30, mp_fill); move.set_name(mk20, "L20") mk21 = move.make(p21, pc0, mp_fill); move.set_name(mk21, "L21") mkc1 = move.make(pc0, p31, mp_fill); move.set_name(mkc1, "Lc1") mk22 = move.make(p22, pc1, mp_fill); move.set_name(mk22, "L22") mkc2 = move.make(pc1, p32, mp_fill); move.set_name(mkc2, "Lc2") mk23 = move.make(p23, pc2, mp_fill); move.set_name(mk23, "L23") mkc3 = move.make(pc2, p33, mp_fill); move.set_name(mkc3, "Lc3") mk24 = move.make(p24, pc3, mp_fill); move.set_name(mk24, "L24") mkc4 = move.make(pc3, p34, mp_fill); move.set_name(mkc4, "Lc4") mk25 = move.make(p25, pc4, mp_fill); move.set_name(mk25, "L25") mkc5 = move.make(pc4, p35, mp_fill); move.set_name(mkc5, "Lc5") mk30 = move.make(p30, p40, mp_fill); move.set_name(mk30, "L30") mk31 = move.make(p35, pd0, mp_fill); move.set_name(mk31, "L31") mkd1 = move.make(pd0, p41, mp_fill); move.set_name(mkd1, "Ld1") # Join them into paths: PFS = [] PLS = [] if version == 0: # Each filling path is a single move: for mv in mv00, mv10, mv20,mv21,mv22, mv30,mv31,mv32, mv40: ph = path.from_moves([mv]) path.set_name(ph, move.get_name(mv).replace("M","F"), False) PFS.append(ph) # Trivial path at starting point: phorg = path.from_points((org,), None, None) PFS.append(phorg) # Links may have 1 or 2 traces: for MLS in ( (mk00,), (mk01,mka1,), (mk10,), (mk11,mkb1,), (mk20,), (mk21,mkc1,), (mk22,mkc2,), (mk23,mkc3,), (mk24,mkc4,), (mk25,mkc5,), (mk30,), (mk31,mkd1,) ): ph = path.from_moves(MLS) path.set_name(ph, "L%d" % len(PLS), False) PLS.append(ph) else: # Single filling path -- define the list {TRS} of traces to be used, in order: if version == 1: # Scanline order with consistent directions, no links: TRS = [ mv00, mv10, mv20,mv21,mv22, mv30,mv31,mv32, mv40, ] elif version == 2: # Scanline order with alternating directions, links: TRS = [ mv00, mk01,mka1, move.rev(mv10), mv20,mv21,mv22, mk25,mkc5, move.rev(mv32),move.rev(mv31),move.rev(mv30), mk30, mv40, ] elif version == 3: # Optimal(?) path: TRS = [ mv00, mk01,mka1, move.rev(mv10), move.rev(mv21), mk22,mkc2, mv31, mv22, mk25,mkc5, move.rev(mv32), move.rev(mv40), move.rev(mk30), mv30, move.rev(mkc1), move.rev(mk21), move.rev(mv20), ] # Now join them with jumps as needed: MVS = []; p = org; for mv in TRS: q = move.pini(mv) if p != q: jm = move.make(p, q, mp_jump) move.set_name(jm, move.get_name(mv).replace("M","J")) MVS.append(jm) MVS.append(mv) p = move.pfin(mv) ph = path.from_moves(MVS) path.set_name(ph, "F", False) PFS.append(ph) return PFS, PLS # ---------------------------------------------------------------------- def make_figure(version, mp_cont, mp_fill, mp_jump): if version > 3: sys.stderr.write("!! no version %d for {make_figure}" % version) return None, None, None # Key dimensions and coordinates: wdc = move_parms.width(mp_cont) wdf = move_parms.width(mp_fill) off = (wdf + wdc)/2 # Offset of contour axis from filling axes/endpoints. # All coords refer to the axes and endpoints traces. xLo = 0 # {X} coord of W side of filling. yLo = 0 # {Y} coord of S side of filling. RS = 2*wdf # Radius of E semicircle of filling. xS = xLo + 9*wdf # {X} coord of center of E semicirle yS = yLo + RS # {Y} coord of center of E semicircle. yHi = yS + RS # {Y} coord of N side. yB = yS + 0.5*wdf # {Y} coord of centers of holes. xB0 = xLo + 3*wdf # {X} coord of center of W hole. xB1 = xLo + 7*wdf # {X} coord of center of E hole. RB = 1.5*wdf # Radius of holes at the filling. xD = xLo + 4*wdf # {X} coord of E edge of dent at SE corner. yD = yS # {Y} coord of N edge of dent at SE corner. PCS = make_figure_contour(mp_cont, xLo,yLo, xS,yS,RS, yHi, xB0,xB1,yB,RB, xD,yD, off) PFS,PLS = make_figure_filling(mp_fill, mp_jump, xLo,yLo, xS,yS,RS, yHi, xB0,xB1,yB,RB, xD,yD, wdf, version) return PCS,PFS,PLS # ----------------------------------------------------------------------