def update(self, L, B, T): """ Update the 3D view printing annotations. @param L Ship length. @param B Ship beam. @param T Ship draft. """ # Destroy all previous entities self.clean() # Draw base line xStart = -0.6 * L xEnd = 0.6 * L baseLine = Part.makeLine((xStart, 0, 0), (xEnd, 0, 0)) Part.show(baseLine) objs = FreeCAD.ActiveDocument.Objects self.baseLine = objs[len(objs) - 1] self.baseLine.Label = 'BaseLine' self.baseLineLabel = DrawText('BaseLineText', str(Translator.translate('Base line')), Base.Vector(xEnd, 0, 0)) # Draw free surface fsLine = Part.makeLine((xStart, 0, T), (xEnd, 0, T)) Part.show(fsLine) objs = FreeCAD.ActiveDocument.Objects self.fsLine = objs[len(objs) - 1] self.fsLine.Label = 'FreeSurface' self.fsLineLabel = DrawText('FSText', str(Translator.translate('Free surface')), Base.Vector(xEnd, 0, T)) # Draw forward perpendicular zStart = -0.1 * T zEnd = 1.1 * T fpLine = Part.makeLine((0.5 * L, 0, zStart), (0.5 * L, 0, zEnd)) Part.show(fpLine) objs = FreeCAD.ActiveDocument.Objects self.fpLine = objs[len(objs) - 1] self.fpLine.Label = 'ForwardPerpendicular' self.fpLineLabel = DrawText( 'FPText', str(Translator.translate('Forward perpendicular')), Base.Vector(0.5 * L, 0, zEnd)) # Draw after perpendicular apLine = Part.makeLine((-0.5 * L, 0, zStart), (-0.5 * L, 0, zEnd)) Part.show(apLine) objs = FreeCAD.ActiveDocument.Objects self.apLine = objs[len(objs) - 1] self.apLine.Label = 'AfterPerpendicular' self.apLineLabel = DrawText( 'APText', str(Translator.translate('After perpendicular')), Base.Vector(-0.5 * L, 0, zEnd)) # Draw amin frame amLine = Part.makeLine((0, -0.5 * B, zStart), (0, -0.5 * B, zEnd)) Part.show(amLine) objs = FreeCAD.ActiveDocument.Objects self.amLine = objs[len(objs) - 1] self.amLine.Label = 'AminFrame' self.amLineLabel = DrawText('AMText', str(Translator.translate('Amin frame')), Base.Vector(0, -0.5 * B, zEnd))
def update(self, names, pos): """ Update the 3D view printing annotations. @param names Weight names. @param pos Weight positions (FreeCAD::Base::Vector). """ # Destroy all previous entities self.clean() for i in range(0, len(names)): # Draw gravity line line = Part.makeLine((pos[i].x,pos[i].y,pos[i].z),(pos[i].x,pos[i].y,pos[i].z - 9.81)) Part.show(line) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'Line' # Draw circles circle = Part.makeCircle(0.5, pos[i], Base.Vector(1.0,0.0,0.0)) Part.show(circle) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'CircleX' circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0,1.0,0.0)) Part.show(circle) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'CircleY' circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0,0.0,1.0)) Part.show(circle) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'CircleZ' # Draw annotation self.objects.append(DrawText(names[i] + 'Text', names[i], Base.Vector(pos[i].x+1.0,pos[i].y,pos[i].z)))
def update(self, names, pos): """ Update the 3D view printing annotations. @param names Weight names. @param pos Weight positions (FreeCAD::Base::Vector). """ # Destroy all previous entities self.clean() for i in range(0, len(names)): # Draw gravity line line = Part.makeLine((pos[i].x, pos[i].y, pos[i].z), (pos[i].x, pos[i].y, pos[i].z - 9.81)) Part.show(line) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'Line' # Draw circles circle = Part.makeCircle(0.5, pos[i], Base.Vector(1.0, 0.0, 0.0)) Part.show(circle) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'CircleX' circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0, 1.0, 0.0)) Part.show(circle) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'CircleY' circle = Part.makeCircle(0.5, pos[i], Base.Vector(0.0, 0.0, 1.0)) Part.show(circle) objs = FreeCAD.ActiveDocument.Objects self.objects.append(objs[-1]) objs[-1].Label = names[i] + 'CircleZ' # Draw annotation self.objects.append( DrawText(names[i] + 'Text', names[i], Base.Vector(pos[i].x + 1.0, pos[i].y, pos[i].z)))
def update(self, L, B, T): """ Update the 3D view printing annotations. @param L Ship length. @param B Ship beam. @param T Ship draft. """ # Destroy all previous entities self.clean() # Draw base line xStart = -0.6*L; xEnd = 0.6*L; baseLine = Part.makeLine((xStart,0,0),(xEnd,0,0)) Part.show(baseLine) objs = FreeCAD.ActiveDocument.Objects self.baseLine = objs[len(objs)-1] self.baseLine.Label = 'BaseLine' self.baseLineLabel = DrawText('BaseLineText', str(Translator.translate('Base line')), Base.Vector(xEnd,0,0)) # Draw free surface fsLine = Part.makeLine((xStart,0,T),(xEnd,0,T)) Part.show(fsLine) objs = FreeCAD.ActiveDocument.Objects self.fsLine = objs[len(objs)-1] self.fsLine.Label = 'FreeSurface' self.fsLineLabel = DrawText('FSText', str(Translator.translate('Free surface')), Base.Vector(xEnd,0,T)) # Draw forward perpendicular zStart = -0.1*T zEnd = 1.1*T fpLine = Part.makeLine((0.5*L,0,zStart),(0.5*L,0,zEnd)) Part.show(fpLine) objs = FreeCAD.ActiveDocument.Objects self.fpLine = objs[len(objs)-1] self.fpLine.Label = 'ForwardPerpendicular' self.fpLineLabel = DrawText('FPText', str(Translator.translate('Forward perpendicular')), Base.Vector(0.5*L,0,zEnd)) # Draw after perpendicular apLine = Part.makeLine((-0.5*L,0,zStart),(-0.5*L,0,zEnd)) Part.show(apLine) objs = FreeCAD.ActiveDocument.Objects self.apLine = objs[len(objs)-1] self.apLine.Label = 'AfterPerpendicular' self.apLineLabel = DrawText('APText', str(Translator.translate('After perpendicular')), Base.Vector(-0.5*L,0,zEnd)) # Draw amin frame amLine = Part.makeLine((0,-0.5*B,zStart),(0,-0.5*B,zEnd)) Part.show(amLine) objs = FreeCAD.ActiveDocument.Objects self.amLine = objs[len(objs)-1] self.amLine.Label = 'AminFrame' self.amLineLabel = DrawText('AMText', str(Translator.translate('Amin frame')), Base.Vector(0,-0.5*B,zEnd))
def create_line(start, stop): """ Creates and returns a FreeCAD line from a given set of start and stop coordinates Expects start and stop to be numpy arrays """ assert start.shape == (3, ) or start.shape == (1, 3) assert stop.shape == (3, ) or stop.shape == (1, 3) assert any(np.not_equal( start, stop)), "Start and stop coordinate should not be identical" start = tuple(start) stop = tuple(stop) return Part.makeLine(start, stop)
def upper_tabletop_3(d, dressup=True): s = 35 x1 = d["length"] / 2.0 y1 = d["width"] / 2.0 x2 = x1 - 25 y2 = y1 - 25 p = [None] * 12 p[0] = Base.Vector(-x1, y2, 0) p[1] = Base.Vector(-x2, y1, 0) p[3] = Base.Vector(x2, y1, 0) p[4] = Base.Vector(x1, y2, 0) p[6] = Base.Vector(x1, -y2, 0) p[7] = Base.Vector(x2, -y1, 0) p[9] = Base.Vector(-x2, -y1, 0) p[10] = Base.Vector(-x1, -y2, 0) p[2] = dc.model.sagpoint(p[1], p[3], s) p[5] = dc.model.sagpoint(p[4], p[6], s) p[8] = dc.model.sagpoint(p[7], p[9], s) p[11] = dc.model.sagpoint(p[10], p[0], s) wire = [ Part.makeLine(p[0], p[1]), dc.model.makeArc(p[1:4]), Part.makeLine(p[3], p[4]), dc.model.makeArc(p[4:7]), Part.makeLine(p[6], p[7]), dc.model.makeArc(p[7:10]), Part.makeLine(p[9], p[10]), dc.model.makeArc([p[10], p[11], p[0]]) ] face = Part.Face(Part.Wire(wire)) m = face.extrude(Base.Vector(0, 0, d["upper_tabletop_t"])) m = dc.model.fillet_edges_by_length(m, 60, d["upper_tabletop_t"]) print("Upper tabletop length: ", d["length"]) print("Upper tabletop width: ", d["width"]) ccx = d["length"] - 2 * math.sqrt( ((d["cx"] + d["leg_distance_from_corner"])**2) / 2.0) ccy = d["width"] - 2 * math.sqrt( ((d["cx"] + d["leg_distance_from_corner"])**2) / 2.0) hx = ccx / 2.0 hy = ccy / 2.0 hole_points = [ Base.Vector(hx, hy, 0), Base.Vector(-hx, hy, 0), Base.Vector(-hx, -hy, 0), Base.Vector(hx, -hy, 0) ] a = 135 for p in hole_points: hole = Part.makeCylinder(d["hole_dia_tabletop"] / 2.0, d["upper_tabletop_t"] / 2.0, p, Base.Vector(0, 0, 1), 360) insert_1 = Part.makeBox(d["leg_t"], d["insertion_width_1"], d["insertion_length"]) insert_1 = dc.model.fillet_edges_by_length(insert_1, d["leg_edge_radii"], d["insertion_length"]) insert_1.translate(Base.Vector(-d["leg_t"] / 2, -d["cx"], 0)) insert_1.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), a) insert_1.translate(p) insert_2 = Part.makeBox(d["leg_t"], d["insertion_width_2"], d["insertion_length"]) insert_2 = dc.model.fillet_edges_by_length(insert_2, d["leg_edge_radii"], d["insertion_length"]) insert_2.translate( Base.Vector(-d["leg_t"] / 2, -d["insertion_width_3"] / 2.0, 0)) insert_2.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), a) insert_2.translate(p) m = m.cut(insert_1).cut(insert_2).cut(hole) a = a + 90 if dressup: m = dc.model.fillet_edges_longer_than(m, d["tabletop_edge_radii"], 300) m.translate(Base.Vector(0, 0, -d["upper_tabletop_t"])) return m
def leg(d, dressup=True): s1 = d["leg_s1"] s2 = d["leg_s2"] s3 = d["leg_s3"] s4 = d["leg_s4"] s5 = d["leg_s5"] x0 = d["insertion_width_1"] x1 = 105 x2 = d["cx"] - d["insertion_width_3"] / 2.0 x3 = x2 + d["insertion_width_2"] x4 = d["cx"] + d["insertion_width_3"] / 2.0 x5 = x2 - 20 x6 = 100 x7 = x6 - 50 y0 = d["height"] - d["upper_tabletop_t"] + d["insertion_length"] y1 = d["height"] - d["upper_tabletop_t"] - 5 y2 = y0 - 10 y3 = d["height_1"] + 100 y4 = d["height_1"] - d["insertion_length"] y5 = y4 + 15 print("Leg length: ", y0) print("Leg width: ", x3) p = [None] * 21 p[0] = Base.Vector(0, y0, 0) p[1] = Base.Vector(x0, y0, 0) p[2] = Base.Vector(x0, y1, 0) p[4] = Base.Vector(x1, y3, 0) p[6] = Base.Vector(x2, y1, 0) p[7] = Base.Vector(x2, y0, 0) p[8] = Base.Vector(x3, y0, 0) p[9] = Base.Vector(x3, y1, 0) p[11] = Base.Vector(x4, y5, 0) p[12] = Base.Vector(x4, y4, 0) p[13] = Base.Vector(x2, y4, 0) p[14] = Base.Vector(x2, y5, 0) p[15] = Base.Vector(x5, y5, 0) p[17] = Base.Vector(x6, 0, 0) p[18] = Base.Vector(x7, 0, 0) p[20] = Base.Vector(0, y2, 0) p[3] = dc.model.sagpoint(p[2], p[4], s1) p[5] = dc.model.sagpoint(p[4], p[6], s2) p[10] = dc.model.sagpoint(p[9], p[11], s3) p[16] = dc.model.sagpoint(p[15], p[17], s4) p[19] = dc.model.sagpoint(p[18], p[20], s5) wire = [ Part.makeLine(p[0], p[1]), Part.makeLine(p[1], p[2]), dc.model.makeArc(p[2:5]), dc.model.makeArc(p[4:7]), Part.makeLine(p[6], p[7]), Part.makeLine(p[7], p[8]), Part.makeLine(p[8], p[9]), dc.model.makeArc(p[9:12]), Part.makeLine(p[11], p[12]), Part.makeLine(p[12], p[13]), Part.makeLine(p[13], p[14]), Part.makeLine(p[14], p[15]), dc.model.makeArc(p[15:18]), Part.makeLine(p[17], p[18]), dc.model.makeArc(p[18:]), Part.makeLine(p[20], p[0]) ] face = Part.Face(Part.Wire(wire)) m = face.extrude(Base.Vector(0, 0, d["leg_t"])) m = dc.model.fillet_edge_xy(m, 7, p[2]) m = dc.model.fillet_edge_xy(m, 12, p[4]) m = dc.model.fillet_edge_xy(m, 7, p[6]) m = dc.model.fillet_edge_xy(m, 7, p[9]) m = dc.model.fillet_edge_xy(m, 7, p[14]) m = dc.model.fillet_edge_xy(m, 12, p[15]) m = dc.model.fillet_edge_xy(m, 30, p[20]) m.rotate(Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), 90) m.translate(Base.Vector(0, d["leg_t"] / 2.0, 0)) hole = Part.makeCylinder( d["hole_dia_leg"] / 2.0, d["height"], Base.Vector(d["cx"], 0, d["height_1"] - d["insertion_length"]), Base.Vector(0, 0, 1), 360) m = m.cut(hole) if dressup: m = dc.model.fillet_edges_longer_than(m, d["leg_edge_radii"], 95) return m
def lower_tabletop_3(d, dressup=True): ccx = d["length"] - 2 * math.sqrt( ((d["cx"] + d["leg_distance_from_corner"])**2) / 2.0) ccy = d["width"] - 2 * math.sqrt( ((d["cx"] + d["leg_distance_from_corner"])**2) / 2.0) length = ccx + (2 * d["leg_distance_from_corner"] + d["insertion_width_3"]) / math.sqrt(2.0) width = ccy + (2 * d["leg_distance_from_corner"] + d["insertion_width_3"]) / math.sqrt(2.0) print("Lower tabletop length: ", length) print("Lower tabletop width: ", width) x1 = length / 2.0 y1 = width / 2.0 x2 = x1 - 25 y2 = y1 - 25 p = [None] * 12 p[0] = Base.Vector(-x1, y2, 0) p[1] = Base.Vector(-x2, y1, 0) p[3] = Base.Vector(x2, y1, 0) p[4] = Base.Vector(x1, y2, 0) p[6] = Base.Vector(x1, -y2, 0) p[7] = Base.Vector(x2, -y1, 0) p[9] = Base.Vector(-x2, -y1, 0) p[10] = Base.Vector(-x1, -y2, 0) p[2] = dc.model.sagpoint(p[1], p[3], -45) p[5] = dc.model.sagpoint(p[4], p[6], -45) p[8] = dc.model.sagpoint(p[7], p[9], -45) p[11] = dc.model.sagpoint(p[10], p[0], -45) wire = [ Part.makeLine(p[0], p[1]), dc.model.makeArc(p[1:4]), Part.makeLine(p[3], p[4]), dc.model.makeArc(p[4:7]), Part.makeLine(p[6], p[7]), dc.model.makeArc(p[7:10]), Part.makeLine(p[9], p[10]), dc.model.makeArc([p[10], p[11], p[0]]) ] face = Part.Face(Part.Wire(wire)) m = face.extrude(Base.Vector(0, 0, d["lower_tabletop_t"])) m = dc.model.fillet_edges_by_length(m, 20, d["lower_tabletop_t"]) hx = ccx / 2.0 hy = ccy / 2.0 hole_points = [ Base.Vector(hx, hy, 0), Base.Vector(-hx, hy, 0), Base.Vector(-hx, -hy, 0), Base.Vector(hx, -hy, 0) ] a = 45 for p in hole_points: hole = Part.makeCylinder(d["hole_dia_tabletop"] / 2.0, d["lower_tabletop_t"], p, Base.Vector(0, 0, 1), 360) insert = Part.makeBox(d["leg_t"], d["insertion_width_3"], d["insertion_length"]) insert = dc.model.fillet_edges_by_length(insert, d["leg_edge_radii"], d["insertion_length"]) insert.translate( Base.Vector(-d["leg_t"] / 2, -d["insertion_width_3"] / 2, 0)) insert.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), -a) insert.translate(p) m = m.cut(hole).cut(insert) a = a + 90 if dressup: m = dc.model.fillet_edges_longer_than(m, d["tabletop_edge_radii"], 150) m.translate(Base.Vector(0, 0, -d["lower_tabletop_t"])) return m
def externalFaces(self, shape): """ Returns detected external faces. @param shape Shape where external faces wanted. @return List of external faces detected. """ result = [] faces = shape.Faces bbox = shape.BoundBox L = bbox.XMax - bbox.XMin B = bbox.YMax - bbox.YMin T = bbox.ZMax - bbox.ZMin dist = math.sqrt(L*L + B*B + T*T) FreeCAD.Console.PrintMessage("Computing external faces...\n") # Valid/unvalid faces detection loop for i in range(0,len(faces)): FreeCAD.Console.PrintMessage("\t%d / %d\n" % (i+1, len(faces))) f = faces[i] # Create a line normal to surface at middle point u = 0.0 v = 0.0 try: surf = f.Surface u = 0.5*(surf.getUKnots()[0]+surf.getUKnots()[-1]) v = 0.5*(surf.getVKnots()[0]+surf.getVKnots()[-1]) except: cog = f.CenterOfMass [u,v] = f.Surface.parameter(cog) p0 = f.valueAt(u,v) try: n = f.normalAt(u,v).normalize() except: continue p1 = p0 + n.multiply(1.5*dist) line = Part.makeLine(p0, p1) # Look for faces in front of this nPoints = 0 for j in range(0,len(faces)): f2 = faces[j] section = self.lineFaceSection(line, f2) if len(section) <= 2: continue # Add points discarding start and end nPoints = nPoints + len(section) - 2 # In order to avoid special directions we can modify line # normal a little bit. angle = 5 line.rotate(p0,Vector(1,0,0),angle) line.rotate(p0,Vector(0,1,0),angle) line.rotate(p0,Vector(0,0,1),angle) nPoints2 = 0 for j in range(0,len(faces)): if i == j: continue f2 = faces[j] section = self.lineFaceSection(line, f2) if len(section) <= 2: continue # Add points discarding start and end nPoints2 = nPoints + len(section) - 2 # If the number of intersection points is pair, is a # external face. So if we found an odd points intersection, # face must be discarded. if (nPoints % 2) or (nPoints2 % 2): continue result.append(f) return result
def externalFaces(self, shape): """ Returns detected external faces. @param shape Shape where external faces wanted. @return List of external faces detected. """ result = [] faces = shape.Faces bbox = shape.BoundBox L = bbox.XMax - bbox.XMin B = bbox.YMax - bbox.YMin T = bbox.ZMax - bbox.ZMin dist = math.sqrt(L * L + B * B + T * T) FreeCAD.Console.PrintMessage("Computing external faces...\n") # Valid/unvalid faces detection loop for i in range(0, len(faces)): FreeCAD.Console.PrintMessage("\t%d / %d\n" % (i + 1, len(faces))) f = faces[i] # Create a line normal to surface at middle point u = 0.0 v = 0.0 try: surf = f.Surface u = 0.5 * (surf.getUKnots()[0] + surf.getUKnots()[-1]) v = 0.5 * (surf.getVKnots()[0] + surf.getVKnots()[-1]) except: cog = f.CenterOfMass [u, v] = f.Surface.parameter(cog) p0 = f.valueAt(u, v) try: n = f.normalAt(u, v).normalize() except: continue p1 = p0 + n.multiply(1.5 * dist) line = Part.makeLine(p0, p1) # Look for faces in front of this nPoints = 0 for j in range(0, len(faces)): f2 = faces[j] section = self.lineFaceSection(line, f2) if len(section) <= 2: continue # Add points discarding start and end nPoints = nPoints + len(section) - 2 # In order to avoid special directions we can modify line # normal a little bit. angle = 5 line.rotate(p0, Vector(1, 0, 0), angle) line.rotate(p0, Vector(0, 1, 0), angle) line.rotate(p0, Vector(0, 0, 1), angle) nPoints2 = 0 for j in range(0, len(faces)): if i == j: continue f2 = faces[j] section = self.lineFaceSection(line, f2) if len(section) <= 2: continue # Add points discarding start and end nPoints2 = nPoints + len(section) - 2 # If the number of intersection points is pair, is a # external face. So if we found an odd points intersection, # face must be discarded. if (nPoints % 2) or (nPoints2 % 2): continue result.append(f) return result
def leg(d, dressup=True): corner_protection = 14 s1 = d["leg_s1"] s2 = d["leg_s2"] s3 = d["leg_s3"] s4 = d["leg_s4"] x0 = d["cx"] + d["insertion_width"] / 2.0 + corner_protection x1 = d["cx"] - d["insertion_width"] / 2.0 + corner_protection x2 = x1 - 25 x3 = 100 x4 = 80 x5 = x3 - 55 y0 = d["height"] y2 = d["height_1"] - d["tabletop_t"] + d["insertion_length"] y1 = y2 - 12 y3 = y2 - d["insertion_length"] y5 = d["height_2"] - d["insertion_length"] y4 = y5 + d["insertion_length"] y6 = y5 + 12 y7 = y0 - 30 p = [None] * 19 p[0] = Base.Vector(0, y0, 0) p[1] = Base.Vector(x4, y0, 0) p[3] = Base.Vector(x2, y1, 0) p[4] = Base.Vector(x1, y1, 0) p[5] = Base.Vector(x1, y2, 0) p[6] = Base.Vector(x0, y2, 0) p[7] = Base.Vector(x0, y3, 0) p[9] = Base.Vector(x0, y4, 0) p[10] = Base.Vector(x0, y5, 0) p[11] = Base.Vector(x1, y5, 0) p[12] = Base.Vector(x1, y6, 0) p[13] = Base.Vector(x2, y6, 0) p[15] = Base.Vector(x3, 0, 0) p[16] = Base.Vector(x5, 0, 0) p[18] = Base.Vector(0, y7, 0) p[2] = dc.model.sagpoint(p[1], p[3], s1) p[8] = dc.model.sagpoint(p[7], p[9], s2) p[14] = dc.model.sagpoint(p[13], p[15], s3) p[17] = dc.model.sagpoint(p[16], p[18], s4) wire = [ Part.makeLine(p[0], p[1]), dc.model.makeArc(p[1:4]), Part.makeLine(p[3], p[4]), Part.makeLine(p[4], p[5]), Part.makeLine(p[5], p[6]), Part.makeLine(p[6], p[7]), dc.model.makeArc(p[7:10]), Part.makeLine(p[9], p[10]), Part.makeLine(p[10], p[11]), Part.makeLine(p[11], p[12]), Part.makeLine(p[12], p[13]), dc.model.makeArc(p[13:16]), Part.makeLine(p[15], p[16]), dc.model.makeArc([p[16], p[17], p[18]]), Part.makeLine(p[18], p[0]) ] face = Part.Face(Part.Wire(wire)) m = face.extrude(Base.Vector(0, 0, d["leg_t"])) m = dc.model.fillet_edge_xy(m, 100, p[18]) m = dc.model.fillet_edge_xy(m, 20, p[3]) m = dc.model.fillet_edge_xy(m, 8, p[4]) m = dc.model.fillet_edge_xy(m, 8, p[12]) m = dc.model.fillet_edge_xy(m, 20, p[13]) m.rotate(Base.Vector(0, 0, 0), Base.Vector(1, 0, 0), 90) m.translate(Base.Vector(-corner_protection, d["leg_t"] / 2.0, 0)) hole = Part.makeCylinder(d["hole_dia_leg"] / 2.0, d["height"], Base.Vector(d["cx"], 0, 0), Base.Vector(0, 0, 1), 360) m = m.cut(hole) corner_cutout = Part.makeBox(4.0 * d["leg_t"], 4.0 * d["leg_t"], d["glass_t"] + 2.0) corner_cutout.rotate(Base.Vector(0, 0, 0), Base.Vector(0, 0, 1), -45.0) corner_cutout.translate( Base.Vector(-2, 0, d["height"] - d["glass_t"] - 2.0)) m = m.cut(corner_cutout) if dressup: m = dc.model.fillet_edges_longer_than(m, 7, 100) return m