def plane_make_part3D(self, thepart, pconfig): self.generate_part3D(thepart, pconfig) # for cutout in thepart.cutouts3D: # for c in cutout: # thepart.border3D = thepart.border3D - c subparts = [] for sp in thepart.parts: if hasattr(sp, 'subpart') and sp.subpart: self.make_part3D(sp, pconfig) if hasattr(sp, 'border3D'): subparts.append(sp.border3D) if len(subparts): if hasattr(thepart, 'border3D'): thepart.border3D=solid.union()(thepart.border3D,*subparts) else: thepart.border3D=solid.union()(*subparts) if not hasattr(thepart, 'border3D'): return False cutouts = [thepart.border3D] for cutout in thepart.cutouts3D: for c in cutout: cutouts.append(c) thepart.border3D = solid.difference()(*cutouts) # 3D transformations can only be applied to parts, so we can just go up the tree p = thepart c=0 print p while(p and type(p) is not Plane):# and (c==0 or not p.renderable() )): p.rotations_to_3D() if hasattr(p, 'transform') and p.transform is not None and p.transform is not False: print p.transform if 'matrix3D' in p.transform: if type(p.transform['matrix3D'][0]) is list or type(p.transform['matrix3D'][0]) is Vec: thepart.border3D=solid.translate([-p.transform['matrix3D'][0][0], -p.transform['matrix3D'][0][1],-p.transform['matrix3D'][0][2]])(thepart.border3D) thepart.border3D=solid.multmatrix(m=p.transform['matrix3D'][1])(thepart.border3D) thepart.border3D=solid.translate([p.transform['matrix3D'][0][0], p.transform['matrix3D'][0][1],p.transform['matrix3D'][0][2]])(thepart.border3D) else: thepart.border3D=solid.multmatrix(m=p.transform['matrix3D'])(thepart.border3D) if 'rotate3D' in p.transform: if type(p.transform['rotate3D'][0]) is list or type(p.transform['rotate3D'][0]) is Vec: thepart.border3D=solid.translate([-p.transform['rotate3D'][0][0], -p.transform['rotate3D'][0][1],-p.transform['rotate3D'][0][2]])(thepart.border3D) thepart.border3D=solid.rotate([p.transform['rotate3D'][1][0], p.transform['rotate3D'][1][1],p.transform['rotate3D'][1][2] ])(thepart.border3D) thepart.border3D=solid.translate([p.transform['rotate3D'][0][0], p.transform['rotate3D'][0][1],p.transform['rotate3D'][0][2]])(thepart.border3D) else: thepart.border3D=solid.rotate([p.transform['rotate3D'][0], p.transform['rotate3D'][1],p.transform['rotate3D'][2] ])(thepart.border3D) if 'translate3D' in p.transform: thepart.border3D=solid.translate([p.transform['translate3D'][0], p.transform['translate3D'][1],p.transform['translate3D'][2] ])(thepart.border3D) c+=1 p=p.parent
def plane_make_part3D(self, thepart, pconfig): self.generate_part3D(thepart, pconfig) # for cutout in thepart.cutouts3D: # for c in cutout: # thepart.border3D = thepart.border3D - c subparts = [] for sp in thepart.parts: if hasattr(sp, 'subpart') and sp.subpart: self.make_part3D(sp, pconfig) if hasattr(sp, 'border3D'): subparts.append(sp.border3D) if len(subparts): if hasattr(thepart, 'border3D'): thepart.border3D=solid.union()(thepart.border3D,*subparts) else: thepart.border3D=solid.union()(*subparts) if not hasattr(thepart, 'border3D'): return False cutouts = [thepart.border3D] for cutout in thepart.cutouts3D: for c in cutout: cutouts.append(c) thepart.border3D = solid.difference()(*cutouts) # 3D transformations can only be applied to parts, so we can just go up the tree p = thepart c=0 while(p and type(p) is not Plane):# and (c==0 or not p.renderable() )): p.rotations_to_3D() if hasattr(p, 'transform') and p.transform is not None and p.transform is not False: if 'matrix3D' in p.transform: if type(p.transform['matrix3D'][0]) is list or type(p.transform['matrix3D'][0]) is Vec: thepart.border3D=solid.translate([-p.transform['matrix3D'][0][0], -p.transform['matrix3D'][0][1],-p.transform['matrix3D'][0][2]])(thepart.border3D) thepart.border3D=solid.multmatrix(m=p.transform['matrix3D'][1])(thepart.border3D) thepart.border3D=solid.translate([p.transform['matrix3D'][0][0], p.transform['matrix3D'][0][1],p.transform['matrix3D'][0][2]])(thepart.border3D) else: thepart.border3D=solid.multmatrix(m=p.transform['matrix3D'])(thepart.border3D) if 'rotate3D' in p.transform: if type(p.transform['rotate3D'][0]) is list or type(p.transform['rotate3D'][0]) is Vec: thepart.border3D=solid.translate([-p.transform['rotate3D'][0][0], -p.transform['rotate3D'][0][1],-p.transform['rotate3D'][0][2]])(thepart.border3D) thepart.border3D=solid.rotate([p.transform['rotate3D'][1][0], p.transform['rotate3D'][1][1],p.transform['rotate3D'][1][2] ])(thepart.border3D) thepart.border3D=solid.translate([p.transform['rotate3D'][0][0], p.transform['rotate3D'][0][1],p.transform['rotate3D'][0][2]])(thepart.border3D) else: thepart.border3D=solid.rotate([p.transform['rotate3D'][0], p.transform['rotate3D'][1],p.transform['rotate3D'][2] ])(thepart.border3D) if 'translate3D' in p.transform: thepart.border3D=solid.translate([p.transform['translate3D'][0], p.transform['translate3D'][1],p.transform['translate3D'][2] ])(thepart.border3D) c+=1 p=p.parent
def transform_to_point( body: OpenSCADObject, dest_point: Point3, dest_normal: Vector3, src_point: Point3=Point3(0, 0, 0), src_normal: Vector3=Vector3(0, 1, 0), src_up: Vector3=Vector3(0, 0, 1)) -> OpenSCADObject: # Transform body to dest_point, looking at dest_normal. # Orientation & offset can be changed by supplying the src arguments # Body may be: # -- an openSCAD object # -- a list of 3-tuples or PyEuclid Point3s # -- a single 3-tuple or Point3 dest_point = euclidify(dest_point, Point3) dest_normal = euclidify(dest_normal, Vector3) at = dest_point + dest_normal EUC_UP = euclidify(UP_VEC) EUC_FORWARD = euclidify(FORWARD_VEC) EUC_ORIGIN = euclidify(ORIGIN, Vector3) # if dest_normal and src_up are parallel, the transform collapses # all points to dest_point. Instead, use EUC_FORWARD if needed if dest_normal.cross(src_up) == EUC_ORIGIN: if src_up.cross(EUC_UP) == EUC_ORIGIN: src_up = EUC_FORWARD else: src_up = EUC_UP def _orig_euclid_look_at(eye, at, up): ''' Taken from the original source of PyEuclid's Matrix4.new_look_at() prior to 1184a07d119a62fc40b2c6becdbeaf053a699047 (11 Jan 2015), as discussed here: https://github.com/ezag/pyeuclid/commit/1184a07d119a62fc40b2c6becdbeaf053a699047 We were dependent on the old behavior, which is duplicated here: ''' z = (eye - at).normalized() x = up.cross(z).normalized() y = z.cross(x) m = Matrix4.new_rotate_triple_axis(x, y, z) m.d, m.h, m.l = eye.x, eye.y, eye.z return m look_at_matrix = _orig_euclid_look_at(eye=dest_point, at=at, up=src_up) if is_scad(body): # If the body being altered is a SCAD object, do the matrix mult # in OpenSCAD sc_matrix = scad_matrix(look_at_matrix) res = multmatrix(m=sc_matrix)(body) else: body = euclidify(body, Point3) if isinstance(body, (list, tuple)): res = [look_at_matrix * p for p in body] else: res = look_at_matrix * body return res
def __init__(self, cone, x_shear, y_shear): super(DerivativeNoseCone, self).__init__(length=cone.length, thickness=cone.thickness, outer_diameter=cone.outer_diameter, inner_diameter=cone.inner_diameter) shear_matrix = [[1, 0, x_shear / cone.length, 0], [0, 1, y_shear / cone.length, 0], [0, 0, 1, 0], [0, 0, 0, 1]]; self.cone = multmatrix(shear_matrix)(cone.cone)
def standard_hold_down(od, wing_thickness, alpha, angle, left=False): hd= hold_down(od, wing_thickness, alpha, od*0.75, od, angle) x = -1 if left else 1 rectify = 180 if left else 0 ret=rotate([90,rectify,0])( multmatrix([[1,0,0,0], [0,x,0,0], [-0.4,0,1,0], [0,0,0,1]])(hd)) return ret
def shape_at_face(m, ft): center = np.array([0, 0]) panel1 = np.vstack((ft[0], ft[1], center)) panel2 = np.vstack((ft[1], ft[2], center)) panel3 = np.vstack((ft[2], ft[0], center)) panel_angle = 20 def panel_shape(panel_tri): edge_midpoint = 0.5 * (panel_tri[0] + panel_tri[1]) rotation_vector = panel_tri[1] - panel_tri[0] transform = lambda x: solid.translate( edge_midpoint)(solid.rotate(a=panel_angle, v=rotation_vector) (solid.translate(-edge_midpoint)(x))) return transform( solid.linear_extrude(0.01)(solid.polygon(panel_tri * 0.9))) return solid.multmatrix(m)( solid.union()(*[panel_shape(p) for p in (panel1, panel2, panel3)]))
def door(self): forward_offset = self.door_thickness / 2 - 0.5 * nscale_inches # slight merge into frame main_panel = grounded_cube( [self.door_width, self.door_thickness, self.door_height]) horizontal_beam = grounded_cube( [self.door_width, self.door_beam_thickness, self.door_beam_width]) vertical_beam = grounded_cube( [self.door_beam_width, self.door_beam_thickness, self.door_height]) horizontal_offset = (self.door_width - self.door_beam_thickness) / 2 vertical_offset = self.door_height - self.door_beam_thickness / 2 diagonal_offset = (self.door_width - self.door_beam_width) / 2 diagonal_skew = 2 * diagonal_offset / self.door_height diagonal_beam = multmatrix([ [1, 0, diagonal_skew, -diagonal_offset], [0, 1, 0, 0], [0, 0, 1, 0], ])(vertical_beam) beams = horizontal_beam + up(vertical_offset)(horizontal_beam) beams += left(horizontal_offset)(vertical_beam) beams += right(horizontal_offset)(vertical_beam) beams += diagonal_beam return up(self.door_opening_threshold - 0.5 * self.door_oversize)( forward(forward_offset)(main_panel + forward( (self.door_beam_thickness - self.door_thickness) / 2)(beams)))
def path_render3D(self, pconfig, border=False): global _delta, PRECISION, SCALEUP self.rotations_to_3D() config={} config=self.overwrite(config,pconfig) inherited = self.get_config() # if('transformations' in config): config=self.overwrite(config, inherited) if border==False and 'zoffset' in pconfig: zoffset= pconfig['zoffset'] elif 'zoffset' in config and config['zoffset']: zoffset= config['zoffset'] else: zoffset = 0 if 'thickness' not in config: config['thickness']=pconfig['thickness'] if config['z0'] is None or config['z0'] is False: z0=0 else: z0=config['z0'] if border==False: z0 += 1 if (config['z1'] is False or config['z1'] is None) and config['z0'] is not None and config['thickness'] is not None: if border==False: z1 = - config['thickness']- 20 else: z1 = - config['thickness'] else: z1= config['z1'] z0 *=config['zdir'] z1*=config['zdir'] # z0 = - config['thickness'] - z0 # z1 = - config['thickness'] - z1 # try to avoid faces and points touching by offsetting them slightly z0+=_delta z1-=_delta _delta+=0.00001 outline = [] points = self.polygonise(RESOLUTION) # extrude_path = [ Point3(0,0,zoffset + float(z0)), Point3(0,0, zoffset + float(z1)) ] for p in points: outline.append( [round(p[0],PRECISION)*SCALEUP, round(p[1],PRECISION)*SCALEUP ]) outline.append([round(points[0][0],PRECISION)*SCALEUP, round(points[0][1],PRECISION)*SCALEUP]) # outline.append( Point3(p[0], p[1], p[2] )) # outline.append( Point3(points[0][0], points[0][1], points[0][2] )) h = round(abs(z1-z0),PRECISION)*SCALEUP bottom = round((min(z1,z0)+zoffset),PRECISION) *SCALEUP # extruded = extrude_along_path(shape_pts=outline, path_pts=extrude_path) if self.extrude_scale is not None: scale = self.extrude_scale if self.extrude_centre is None: self.extrude_centre = V(0,0) centre = (PSharp(V(0,0)).point_transform(config['transformations']).pos+self.extrude_centre) centre = [centre[0], centre[1]] uncentre = [-centre[0], -centre[1]] extruded = solid.translate([0,0,bottom])( solid.translate(centre)( solid.linear_extrude(height=h, center=False, scale = scale)( solid.translate(uncentre)(solid.polygon(points=outline))))) else: scale = 1 extruded = solid.translate([0,0,bottom])(solid.linear_extrude(height=h, center=False)(solid.polygon(points=outline))) #extruded = translate([0,0,bottom])(linear_extrude(height=h, center=False)(solid.polygon(points=outline))) # if 'isback' in config and config['isback'] and border==False: # extruded = mirror([1,0,0])(extruded ) if 'colour' in config and config['colour']: extruded = solid.color(self.scad_colour(config['colour']))(extruded) if hasattr(self, 'transform') and self.transform is not None and self.transform is not False and 'matrix3D' in self.transform: if type(self.transform['matrix3D'][0]) is list: extruded=solid.translate([-self.transform['rotate3D'][1][0], - self.transform['rotate3D'][1][1]])(extruded) extruded=solid.multmatrix(m=self.transform['matrix3D'][0])(extruded) extruded=solid.translate([self.transform['rotate3D'][1][0], self.transform['rotate3D'][1][1]])(extruded) else: extruded=solid.multmatrix(m=self.transform['matrix3D'])(extruded) if hasattr(self, 'transform') and self.transform is not None and self.transform is not False and 'rotate3D' in self.transform: if type(self.transform['rotate3D'][0]) is list: print [-self.transform['rotate3D'][1][0], - self.transform['rotate3D'][1][1], - self.transform['rotate3D'][1][2]- zoffset] extruded=solid.translate([-self.transform['rotate3D'][1][0], - self.transform['rotate3D'][1][1], - self.transform['rotate3D'][1][2]- zoffset])(extruded) extruded=solid.rotate([self.transform['rotate3D'][0][0], self.transform['rotate3D'][0][1],self.transform['rotate3D'][0][2] ])(extruded) extruded=solid.translate([self.transform['rotate3D'][1][0], self.transform['rotate3D'][1][1], self.transform['rotate3D'][1][1] + zoffset])(extruded) else: extruded=solid.rotate([self.transform['rotate3D'][0], self.transform['rotate3D'][1],self.transform['rotate3D'][2] ])(extruded) if hasattr(self, 'transform') and self.transform is not None and self.transform is not False and 'translate3D' in self.transform: extruded=solid.translate([self.transform['translate3D'][0], self.transform['translate3D'][1],self.transform['translate3D'][2] ])(extruded) return [extruded]
def shape_at_vertex(m, ve): shape = solid.sphere(r=0.05) if len(ve) == highlight_valence: shape = solid.color("red")(shape) return solid.multmatrix(m)(shape)
def shape_at_vertex(m): return solid.multmatrix(m)(solid.utils.up(0.09)(solid.sphere(r=0.12)))
def shape_at_edge(m, el): return solid.multmatrix(m)(solid.utils.rot_z_to_right( solid.cylinder(r1=0.03, r2=0.03, h=el, center=True)))
def shape_at_vertex(m): return solid.multmatrix(m)(solid.sphere(r=0.05))
def shape_at_edge(m, el, e): shape = solid.cylinder(r1=0.03, r2=0.03, h=el, center=True) if any(len(ves[i]) == highlight_valence for i in e): shape = solid.color("red")(shape) return solid.multmatrix(m)(solid.utils.rot_z_to_right(shape))
def path_render3D(self, pconfig, border=False): global _delta, PRECISION, SCALEUP self.rotations_to_3D() config={} config=self.overwrite(config,pconfig) inherited = self.get_config() # if('transformations' in config): config=self.overwrite(config, inherited) if border==False and 'zoffset' in pconfig: zoffset= pconfig['zoffset'] elif 'zoffset' in config and config['zoffset']: zoffset= config['zoffset'] else: zoffset = 0 if 'thickness' not in config: config['thickness']=pconfig['thickness'] if config['z0'] is None or config['z0'] is False: z0=0 else: z0=config['z0'] if border==False: z0 += config['thickness'] +1 if (config['z1'] is False or config['z1'] is None) and config['z0'] is not None and config['thickness'] is not None: if border==False: z1 = - config['thickness']- 20 else: z1 = - config['thickness'] else: z1= config['z1'] z0 *=config['zdir'] z1*=config['zdir'] # z0 = - config['thickness'] - z0 # z1 = - config['thickness'] - z1 # try to avoid faces and points touching by offsetting them slightly z0+=_delta z1-=_delta _delta+=0.00001 outline = [] self.reset_points() points = self.polygonise(RESOLUTION) # extrude_path = [ Point3(0,0,zoffset + float(z0)), Point3(0,0, zoffset + float(z1)) ] for p in points: outline.append( [round(p[0],PRECISION)*SCALEUP, round(p[1],PRECISION)*SCALEUP ]) outline.append([round(points[0][0],PRECISION)*SCALEUP, round(points[0][1],PRECISION)*SCALEUP]) # outline.append( Point3(p[0], p[1], p[2] )) # outline.append( Point3(points[0][0], points[0][1], points[0][2] )) h = round(abs(z1-z0),PRECISION)*SCALEUP bottom = round((min(z1,z0)+zoffset),PRECISION) *SCALEUP # dodgy but working atm if not border and 'isback' in config and config['isback']: pass h = 2*h # extruded = extrude_along_path(shape_pts=outline, path_pts=extrude_path) if self.extrude_scale is not None: scale = self.extrude_scale if self.extrude_centre is None: self.extrude_centre = V(0,0) centre = (PSharp(V(0,0)).point_transform(config['transformations']).pos+self.extrude_centre) centre = [centre[0], centre[1]] uncentre = [-centre[0], -centre[1]] extruded = solid.translate([0,0,bottom])( solid.translate(centre)( solid.linear_extrude(height=h, center=False, scale = scale)( solid.translate(uncentre)(solid.polygon(points=outline))))) else: scale = 1 extruded = solid.translate([0,0,bottom])(solid.linear_extrude(height=h, center=False)(solid.polygon(points=outline))) #extruded = translate([0,0,bottom])(linear_extrude(height=h, center=False)(solid.polygon(points=outline))) # if not border and 'isback' in config and config['isback'] and border==False: # extruded = solid.mirror([1,0,0])(extruded ) if 'colour' in config and config['colour']: extruded = solid.color(self.scad_colour(config['colour']))(extruded) p=self p.rotations_to_3D() while(p and type(p) is not Plane and not ( hasattr(p,'renderable') and p.renderable())):# and (c==0 or not p.renderable() )): if hasattr(p, 'transform') and p.transform is not None and p.transform is not False and 'matrix3D' in p.transform: if type(p.transform['matrix3D'][0]) is list or type(p.transform['matrix3D'][0]) is Vec: extruded=solid.translate([-p.transform['matrix3D'][0][0], -p.transform['matrix3D'][0][1],-p.transform['matrix3D'][0][2]])(extruded) extruded=solid.multmatrix(m=p.transform['matrix3D'][1])(extruded) extruded=solid.translate([p.transform['matrix3D'][0][0], p.transform['matrix3D'][0][1],p.transform['matrix3D'][0][2]])(extruded) else: extruded=solid.multmatrix(m=p.transform['matrix3D'])(extruded) if hasattr(p, 'transform') and p.transform is not None and p.transform is not False and 'rotate3D' in p.transform: if type(p.transform['rotate3D'][0]) is list or type(p.transform['rotate3D'][0]) is Vec: if p.transform['rotate3D'][0]!=[0,0,0]: extruded=solid.translate([-p.transform['rotate3D'][0][0], -p.transform['rotate3D'][0][1],-p.transform['rotate3D'][0][2]])(extruded) extruded=solid.rotate([p.transform['rotate3D'][1][0], p.transform['rotate3D'][1][1],p.transform['rotate3D'][1][2] ])(extruded) if p.transform['rotate3D'][0]!=[0,0,0]: extruded=solid.translate([p.transform['rotate3D'][0][0], p.transform['rotate3D'][0][1],p.transform['rotate3D'][0][2]])(extruded) else: extruded=solid.rotate([p.transform['rotate3D'][0], p.transform['rotate3D'][1],p.transform['rotate3D'][2] ])(extruded) if hasattr(p, 'transform') and p.transform is not None and p.transform is not False and 'translate3D' in p.transform: extruded=solid.translate([p.transform['translate3D'][0], p.transform['translate3D'][1],p.transform['translate3D'][2] ])(extruded) p=p.parent # if (hasattr(p,'renderable') and p.renderable and p.obType == "Part"): # if(p.border is not False and p.border is not None): # if hasattr(self, 'transform') and self.transform is not None and self.transform is not False and 'matrix3D' in self.transform: # if type(self.transform['matrix3D'][0]) is list: # extruded=solid.translate([-self.transform['rotate3D'][0][0], - self.transform['rotate3D'][0][1]])(extruded) # extruded=solid.multmatrix(m=self.transform['matrix3D'][0])(extruded) # extruded=solid.translate([self.transform['rotate3D'][0][0], self.transform['rotate3D'][0][1]])(extruded) # else: # extruded=solid.multmatrix(m=self.transform['matrix3D'])(extruded) # if hasattr(self, 'transform') and self.transform is not None and self.transform is not False and 'rotate3D' in self.transform: # if type(self.transform['rotate3D'][0]) is list or type(self.transform['rotate3D'][0]) is Vec: # extruded=solid.translate([-self.transform['rotate3D'][1][0], - self.transform['rotate3D'][1][1], - self.transform['rotate3D'][1][2]- zoffset])(extruded) # extruded=solid.rotate([self.transform['rotate3D'][0][0], self.transform['rotate3D'][0][1],self.transform['rotate3D'][0][2] ])(extruded) # extruded=solid.translate([self.transform['rotate3D'][1][0], self.transform['rotate3D'][1][1], self.transform['rotate3D'][1][1] + zoffset])(extruded) # else: # extruded=solid.rotate([self.transform['rotate3D'][0], self.transform['rotate3D'][1],self.transform['rotate3D'][2] ])(extruded) # if hasattr(self, 'transform') and self.transform is not None and self.transform is not False and 'translate3D' in self.transform: # extruded=solid.translate([self.transform['translate3D'][0], self.transform['translate3D'][1],self.transform['translate3D'][2] ])(extruded) return [extruded]