def output_arrow_head(op, dim, tip_W, ax_dir, bx_dir, cx_dir): "Draws an arrow head with tip at point {tip}, direction {ax_dir}, length {hd_len}." \ "\n" \ " The directions {bx,dir,cx_dir} must be orthogonal to {ax_dir} and to each other." # World points: eip_W = rn.add(tip_W, rn.scale(-dim.hd_len, ax_dir)) # Base of arrow head. tbm_W = rn.add(eip_W, rn.scale(-0.25 * dim.hd_len, bx_dir)) # Corner B+ of arrow head. tbp_W = rn.add(eip_W, rn.scale(+0.25 * dim.hd_len, bx_dir)) # Corner B- of arrow head. tcm_W = rn.add(eip_W, rn.scale(-0.25 * dim.hd_len, cx_dir)) # Corner C+ of arrow head. tcp_W = rn.add(eip_W, rn.scale(+0.25 * dim.hd_len, cx_dir)) # Corner C- of arrow head. # Image points: tip = img_point(tip_W, dim.map) # Arrow tip. tbm = img_point(tbm_W, dim.map) # Corner B+ of arrow head. tbp = img_point(tbp_W, dim.map) # Corner B- of arrow head. tcm = img_point(tcm_W, dim.map) # Corner C+ of arrow head. tcp = img_point(tcp_W, dim.map) # Corner C- of arrow head. sys.stdout.write( \ ' <path d="M '+ pfm(tcm) +' L '+ pfm(tbm) +' L '+ pfm(tcp) +' L '+ pfm(tbp) +'" stroke="rgb(0,0,0)" fill="rgb(0,0,0)" />\n' \ ' <path d="M '+ pfm(tip) +' L '+ pfm(tbm) +' L '+ pfm(tbp) +'" stroke="rgb(0,0,0)" fill="rgb(0,0,0)" />\n' \ ' <path d="M '+ pfm(tip) +' L '+ pfm(tcm) +' L '+ pfm(tcp) +'" stroke="rgb(0,0,0)" fill="rgb(0,0,0)" />\n' \ )
def output_coord_axis(op, dim, ax_dir, lab_dp, lab_str): "Draws a coordinate axis." \ "\n" \ " The axis goes from the origin to {dim.ax_len*ax_dir}. The arrow tip has" \ " size {dim.hd_len}. The label is {lab_str} offset by {lab_dp} from the tip." # World points: ooo_W = [00, 00, 00] # Origin. tip_W = rn.add(ooo_W, rn.scale(dim.ax_len, ax_dir)) # Tip of axis. # Image points: ooo = img_point(ooo_W, dim.map) # Origin. tip = img_point(tip_W, dim.map) # Axis tip. # Axis line: sys.stdout.write( \ ' <!-- The '+ lab_str +' axis: -->\n' \ ' <path d="M '+ pfm(ooo) +' L '+ pfm(tip) +'" stroke="rgb(0,0,0)"/>\n' \ ) # Tics: # Axis line: sys.stdout.write( \ ' <g stroke="rgb(0,0,0)" fill="rgb(0,0,0)">\n' \ ) ct = dim.ax_unit while (ct < dim.ax_len - dim.hd_len): tic_W = rn.add(ooo_W, rn.scale(ct, ax_dir)) # Axis tic (World). tic = img_point(tic_W, dim.map) # Axis tic (Image). sys.stdout.write( \ ' <circle '+ xyfm(tic,'c') +' r="1px"/>\n' \ ) ct += dim.ax_unit sys.stdout.write( \ ' </g>\n' \ ) # Auxiliary directions perpendicular to the axis: bx_dir = [ax_dir[2], ax_dir[0], ax_dir[1]] # Sideways direction B for arrow tip. cx_dir = [ax_dir[1], ax_dir[2], ax_dir[0]] # Sideways direction C for arrow tip. output_arrow_head(op, dim, tip_W, ax_dir, bx_dir, cx_dir) lab_pos = rn.add(lab_dp, tip) output_label(op, dim, tip, lab_dp, make_italic_style(lab_str)) sys.stdout.write('\n')
def output_label(op, dim, pos, dp, str): "Ouputs a label {str} at image position {pos} displaced by {dp}." if (str != ''): dpx = dp[0] dpy = dp[1] # Compute anchor {anch}: if (dpx < 0): anch = 'end' elif (dpx > 0): anch = 'start' else: anch = 'middle' if (dpy > 0): # Adjust {dpy} for font height: dpy += 0.6 * dim.font_wy elif (dpy == 0): dpy += 0.3 * dim.font_wy pos = rn.add(pos, [dpx, dpy]) sys.stdout.write( \ ' <text '+ xyfm(pos,'') +' stroke="rgb(255,255,255)"' \ ' stroke-width="3px" fill="none" text-anchor="'+ anch +'">'+ str +'</text>\n' \ ' <text '+ xyfm(pos,'') +' stroke="none"' \ ' fill="rgb(0,0,0)" text-anchor="'+ anch +'">'+ str +'</text>\n' \ )
def output_straight_trace(op, dim, ini_W, fin_W, draw, lab_str): "Draws and/or labels a dashed straight line.\n" \ "\n" \ " The line goes from {ini_W} to {fin_W} and is labeled {lab-str}. If {draw}" \ " is FALSE, does not plot it, just writes the label." \ "\n" \ " " # Parameters: dashed = (lab_str == '') if (dashed): style = 'stroke="rgb(0,0,0)" stroke-dasharray="3,4" stroke-dashoffset="9"' else: style = 'stroke="rgb(' + dim.ct_color + ')"' ini = img_point(ini_W, dim.map) # Start point. fin = img_point(fin_W, dim.map) # End point. if (draw): sys.stdout.write( \ ' <path d="M '+ pfm(ini) +' L '+ pfm(fin) +'" ' + style + '/>\n' \ ) # Compute the label position and displacement: mid = rn.scale(0.5, rn.add(ini, fin)) # Midpoint of trace. dtr, ntr = rn.dir(rn.sub(ini, fin)) # Direction and length of trace. dpx = +5 * dtr[1] dpy = -5 * dtr[0] ooo = img_point([00, 00, 00], dim.map) # Origin. if (abs(dpx) > abs(dpy)): if ((mid[0] < ooo[0]) != (dpx < 0)): dpx = -dpx dpy = -dpy else: if ((mid[1] < ooo[1]) != (dpy < 0)): dpx = -dpx dpy = -dpy output_label(op, dim, mid, [dpx, dpy], make_italic_style(lab_str))
def output_circular_trace(op, dim, ctr_W, u_W, v_W, ang_ini, ang_fin, rad, lab_str): "Draws an angular coordinate trace.\n" \ "\n" \ " The arc goes from {d_ini} to {d_fin} given the center {ctr_W}, the plane's ortho" \ " axes {u_W,v_W}, the angle interval {ang_ini,ang_fin}, and the radius {rad}." \ "\n" \ " If the label is not empty, uses solid colored line, else a dashed " # Parameters: dashed = (lab_str == '') ang = ang_ini # Current angle. step = math.pi / 100 # Initial guess for step. if (dashed): down = False # Is the pen down? dlen = 2 # Length of current dash/gap (px). color = '0,0,0' else: down = True # Is the pen down? dlen = 4 # Length of current dash/gap (px). color = dim.ct_color # Compute the dash start and stop points {dini[k],dfin[k]}: dini = [] dfin = [] nd = 0 # Initial point: pos_W = rn.add(ctr_W, vec_from_ang_rad(u_W, v_W, ang_ini, rad)) # Current World point. pos = img_point(pos_W, dim.map) # Current Image point. ctr = img_point(ctr_W, dim.map) # Image arc center. # Loop on steps: while (ang < ang_fin): pos_old = pos # Save previous position. ang_old = ang # Save previous angle. # Find {ang > ang_old} such that the step takes us about {dlen} avawy from {pre} while (True): ang = ang_old + step pos_W = rn.add(ctr_W, vec_from_ang_rad(u_W, v_W, ang, rad)) # Current World point. pos = img_point(pos_W, dim.map) # Current Image point. dst = rn.dist(pos_old, pos) rel = dst / dlen # sys.stderr.write("ang = %6.2f dst = %6.2f dlen = %6.2f rel = %8.4f\n" % (ang,dst,dlen,rel)); if ((rel >= 0.9) and (rel <= 1.1)): break elif (rel < 0.5): step *= 2 elif (rel > 2.0): step /= 2 else: step /= rel # Trim the angle to {ang_fin}: if (ang > ang_fin): ang = ang_fin pos_W = rn.add(ctr_W, vec_from_ang_rad(u_W, v_W, ang, rad)) # Current World point. pos = img_point(pos_W, dim.map) # Current Image point. # Process a gap/dash from {pre} to {pos}: if (down): # Dash: dini[nd:nd] = [pos_old] dfin[nd:nd] = [pos] nd += 1 if (dashed): down = False dlen = 3 else: # Gap: down = True dlen = 4 nd = len(dini) if (not dashed): # Paint the sectors: sys.stdout.write( \ ' <g stroke="none" fill="rgb(100,0,200)" fill-opacity="0.25">\n' \ ) for k in range(nd): sys.stdout.write( \ ' <path d="M '+ pfm(dini[k]) +' L '+ pfm(dfin[k]) +' L '+ pfm(ctr) +'"/>\n' \ ) sys.stdout.write( \ ' </g>\n' \ ) # Draw the arc: sys.stdout.write( \ ' <g stroke="rgb(' + color + ')" fill="none">\n' \ ) for k in range(nd): sys.stdout.write( \ ' <path d="M '+ pfm(dini[k]) +' L '+ pfm(dfin[k]) +'" />\n' \ ) sys.stdout.write( \ ' </g>\n' \ ) # Compute the label position and displacement: ang_mid = (ang_ini + ang_fin) / 2 mid_W = rn.add(ctr_W, vec_from_ang_rad(u_W, v_W, ang_mid, rad)) # Arc midpoint. mid = img_point(mid_W, dim.map) # Midpoint of arc. dmd, emd = rn.dir(rn.sub(mid, ctr)) # Direction from center to midpoint of arc. dpx = 5 * dmd[0] dpy = 5 * dmd[1] output_label(op, dim, mid, [dpx, dpy], make_italic_style(lab_str))
def output_system_planes_CY_SE_SZ(op, dim): # Key World points: ooo_W = [00, 00, 00] # Origin. poo_W = [+1, 00, 00] # +X axis dir. moo_W = [-1, 00, 00] # -X axis dir. opo_W = vec_from_ang_rad([+1, 00, 00], [00, +1, 00], dim.ac_val, 1.0) # +U axis dir. omo_W = vec_from_ang_rad([-1, 00, 00], [00, -1, 00], dim.ac_val, 1.0) # -U axis dir. oop_W = [00, 00, +1] # +Z axis dir. oom_W = [00, 00, -1] # -Z axis dir. # Key Image points: ooo = img_point(ooo_W, dim.map) # Origin. moo = img_point(moo_W, dim.map) # Point -1 on X axis poo = img_point(poo_W, dim.map) # Point +1 on X axis omo = img_point(omo_W, dim.map) # Point -1 on U axis opo = img_point(opo_W, dim.map) # Point +1 on U axis oom = img_point(oom_W, dim.map) # Point -1 on Z axis oop = img_point(oop_W, dim.map) # Point +1 on Z axis opm = img_point(rn.add(opo_W, oom_W), dim.map) # Corner A of UZ square. opp = img_point(rn.add(opo_W, oop_W), dim.map) # Corner B of UZ square. omp = img_point(rn.add(omo_W, oop_W), dim.map) # Corner C of UZ square. omm = img_point(rn.add(omo_W, oom_W), dim.map) # Corner D of UZ square. mop = img_point(rn.add(moo_W, oop_W), dim.map) # Corner A of ZX square. pop = img_point(rn.add(poo_W, oop_W), dim.map) # Corner B of ZX square. pom = img_point(rn.add(poo_W, oom_W), dim.map) # Corner C of ZX square. mom = img_point(rn.add(moo_W, oom_W), dim.map) # Corner D of ZX square. # !!! BUG !!! should compute the ellipse from the map !!! sys.stdout.write( \ ' <!-- The reference planes: -->\n' \ ' <g stroke="rgb(185, 205, 170)" fill="rgb(215, 235, 200)" fill-opacity="0.5">\n' \ ' <polygon points="'+ pfm(moo) +' '+ pfm(ooo) +' '+ pfm(oom) +' '+ pfm(mom) +'"/>\n' \ ' <polygon points="'+ pfm(omo) +' '+ pfm(ooo) +' '+ pfm(oom) +' '+ pfm(omm) +'"/>\n' \ ' <polygon points="'+ pfm(poo) +' '+ pfm(ooo) +' '+ pfm(oom) +' '+ pfm(pom) +'"/>\n' \ ' <polygon points="'+ pfm(opo) +' '+ pfm(ooo) +' '+ pfm(oom) +' '+ pfm(opm) +'"/>\n' \ ' \n' \ ' <ellipse cx="0" cy="14" rx="222" ry="102" transform="translate('+ pfm(ooo) +')rotate(0)"/>\n' \ ' \n' \ ' <polygon points="'+ pfm(moo) +' '+ pfm(ooo) +' '+ pfm(oop) +' '+ pfm(mop) +'"/>\n' \ ' <polygon points="'+ pfm(omo) +' '+ pfm(ooo) +' '+ pfm(oop) +' '+ pfm(omp) +'"/>\n' \ ' <polygon points="'+ pfm(poo) +' '+ pfm(ooo) +' '+ pfm(oop) +' '+ pfm(pop) +'"/>\n' \ ' <polygon points="'+ pfm(opo) +' '+ pfm(ooo) +' '+ pfm(oop) +' '+ pfm(opp) +'"/>\n' \ ' </g>\n' \ ) sys.stdout.write('\n') if (op.frame): # Auxiliary lines for debugging: pmo = img_point([+1, -1, 00], dim.map) # Corner A of XY square. ppo = img_point([+1, +1, 00], dim.map) # Corner B of XY square. mpo = img_point([-1, +1, 00], dim.map) # Corner C of XY square. mmo = img_point([-1, -1, 00], dim.map) # Corner D of XY square. sys.stdout.write( \ ' <polygon points="'+ pfm(pmo) +' '+ pfm(ppo) +' '+ pfm(mpo) +' '+ pfm(mmo) +'" stroke="rgb(177,0,0)" fill="none" />\n' \ ' <path d="M '+ pfm(pmo) +' L '+ pfm(mpo) +'" stroke="rgb(137, 137, 137)"/>\n' \ ' <path d="M '+ pfm(ppo) +' L '+ pfm(mmo) +'" stroke="rgb(137, 137, 137)"/>\n' \ ' <path d="M '+ pfm(moo) +' L '+ pfm(poo) +'" stroke="rgb(137, 137, 137)"/>\n' \ ' <path d="M '+ pfm(omo) +' L '+ pfm(opo) +'" stroke="rgb(137, 137, 137)"/>\n' \ ) sys.stdout.write('\n')
def output_system_planes_CA(op, dim): # Key World points: ooo_W = [00, 00, 00] # Origin. poo_W = [+1, 00, 00] # +X axis dir. moo_W = [-1, 00, 00] # -X axis dir. opo_W = [00, +1, 00] # +Y axis dir. omo_W = [00, -1, 00] # -Y axis dir. oop_W = [00, 00, +1] # +Z axis dir. oom_W = [00, 00, -1] # -Z axis dir. # Key Image points: ooo = img_point(ooo_W, dim.map) # Origin. moo = img_point(moo_W, dim.map) # Point -1 on X axis poo = img_point(poo_W, dim.map) # Point +1 on X axis omo = img_point(omo_W, dim.map) # Point -1 on U axis opo = img_point(opo_W, dim.map) # Point +1 on U axis oom = img_point(oom_W, dim.map) # Point -1 on Z axis oop = img_point(oop_W, dim.map) # Point +1 on Z axis pmo = img_point(rn.add(poo_W, omo_W), dim.map) # Corner A of XY square. ppo = img_point(rn.add(poo_W, opo_W), dim.map) # Corner B of XY square. mpo = img_point(rn.add(moo_W, opo_W), dim.map) # Corner C of XY square. mmo = img_point(rn.add(moo_W, omo_W), dim.map) # Corner D of XY square. opm = img_point(rn.add(opo_W, oom_W), dim.map) # Corner A of UZ square. opp = img_point(rn.add(opo_W, oop_W), dim.map) # Corner B of UZ square. omp = img_point(rn.add(omo_W, oop_W), dim.map) # Corner C of UZ square. omm = img_point(rn.add(omo_W, oom_W), dim.map) # Corner D of UZ square. mop = img_point(rn.add(moo_W, oop_W), dim.map) # Corner A of ZX square. pop = img_point(rn.add(poo_W, oop_W), dim.map) # Corner B of ZX square. pom = img_point(rn.add(poo_W, oom_W), dim.map) # Corner C of ZX square. mom = img_point(rn.add(moo_W, oom_W), dim.map) # Corner D of ZX square. sys.stdout.write( \ ' <!-- The reference planes: -->\n' \ ' <g stroke="rgb(185, 205, 170)" fill="rgb(215, 235, 200)" fill-opacity="0.5">\n' \ ' <polygon points="'+ pfm(moo) +' '+ pfm(ooo) +' '+ pfm(oom) +' '+ pfm(mom) +'"/>\n' \ ' <polygon points="'+ pfm(omo) +' '+ pfm(ooo) +' '+ pfm(oom) +' '+ pfm(omm) +'"/>\n' \ ' <polygon points="'+ pfm(poo) +' '+ pfm(ooo) +' '+ pfm(oom) +' '+ pfm(pom) +'"/>\n' \ ' <polygon points="'+ pfm(opo) +' '+ pfm(ooo) +' '+ pfm(oom) +' '+ pfm(opm) +'"/>\n' \ ' \n' \ ' <polygon points="'+ pfm(pmo) +' '+ pfm(ppo) +' '+ pfm(mpo) +' '+ pfm(mmo) +'"/>\n' \ ' \n' \ ' <polygon points="'+ pfm(moo) +' '+ pfm(ooo) +' '+ pfm(oop) +' '+ pfm(mop) +'"/>\n' \ ' <polygon points="'+ pfm(omo) +' '+ pfm(ooo) +' '+ pfm(oop) +' '+ pfm(omp) +'"/>\n' \ ' <polygon points="'+ pfm(poo) +' '+ pfm(ooo) +' '+ pfm(oop) +' '+ pfm(pop) +'"/>\n' \ ' <polygon points="'+ pfm(opo) +' '+ pfm(ooo) +' '+ pfm(oop) +' '+ pfm(opp) +'"/>\n' \ ' </g>\n' \ ) if (op.frame): # Auxiliary lines for debugging: sys.stdout.write( \ ' <polygon points="'+ pfm(pmo) +' '+ pfm(ppo) +' '+ pfm(mpo) +' '+ pfm(mmo) +'" stroke="rgb(177,0,0)" fill="none" />\n' \ ' <path d="M '+ pfm(pmo) +' L '+ pfm(mpo) +'" stroke="rgb(137, 137, 137)"/>\n' \ ' <path d="M '+ pfm(ppo) +' L '+ pfm(mmo) +'" stroke="rgb(137, 137, 137)"/>\n' \ ' <path d="M '+ pfm(moo) +' L '+ pfm(poo) +'" stroke="rgb(137, 137, 137)"/>\n' \ ' <path d="M '+ pfm(omo) +' L '+ pfm(opo) +'" stroke="rgb(137, 137, 137)"/>\n' \ ) sys.stdout.write('\n')
def vec_from_ang_rad(u, v, ang, rad): "Converts polar coords {ang,rad} to Cartesia, given two axis directions {u,v} in {R^3}." c = rad * cos(ang) s = rad * sin(ang) return rn.add(rn.scale(c, u), rn.scale(s, v))