def binormalFace(self, samp, dist, tol=1e-5, sym=False): face = None if sym: dist /=2.0 ran = self.lastParameter - self.firstParameter pts = list() pars = list() for i in range(samp): t = self.firstParameter + float(i) * ran / (samp-1) pts.append(self.valueAt(t).add(self.binormalAt(t)*float(dist))) pars.append(t) #if self._closed: #pts = pts[:-1] bs = Part.BSplineCurve() bs.approximate(Points = pts, Parameters = pars, DegMin = 3, DegMax = 7, Tolerance = tol) if sym: pts = list() pars = list() for i in range(samp): t = self.firstParameter + float(i) * ran / (samp-1) pts.append(self.valueAt(t).sub(self.binormalAt(t)*float(dist))) pars.append(t) #if self._closed: #pts = pts[:-1] bs2 = Part.BSplineCurve() bs2.approximate(Points = pts, Parameters = pars, DegMin = 3, DegMax = 7, Tolerance = tol) face = Part.makeRuledSurface(bs2.toShape(), bs.toShape()) else: face = Part.makeRuledSurface(self.edgeOnFace, bs.toShape()) if self._closed: surf = face.Surface.copy() surf.setUPeriodic() face = surf.toShape() #nf = face.transformGeometry(self.face.Placement.toMatrix()) return(face.transformGeometry(self.face.Placement.toMatrix()))
def ruled_surface(e1,e2): """ creates a ruled surface between 2 edges, with automatic orientation.""" # Automatic orientation # /src/Mod/Part/App/PartFeatures.cpp#171 p1 = e1.valueAt(e1.FirstParameter) p2 = e1.valueAt(e1.LastParameter) p3 = e2.valueAt(e2.FirstParameter) p4 = e2.valueAt(e2.LastParameter) if e1.Orientation == 'Reversed': p = p1 p1 = p2 p2 = p if e2.Orientation == 'Reversed': p = p3 p3 = p4 p4 = p v1 = p2 - p1 v2 = p3 - p1 n1 = v1.cross(v2) v3 = p3 - p4 v4 = p2 - p4 n2 = v3.cross(v4) if (n1.dot(n2) < 0): e = e2.copy() e.reverse() return(Part.makeRuledSurface(e1,e)) else: return(Part.makeRuledSurface(e1,e2))
def ruled_surface(e1, e2): """ creates a ruled surface between 2 edges, with automatic orientation.""" # Automatic orientation # /src/Mod/Part/App/PartFeatures.cpp#171 p1 = e1.valueAt(e1.FirstParameter) p2 = e1.valueAt(e1.LastParameter) p3 = e2.valueAt(e2.FirstParameter) p4 = e2.valueAt(e2.LastParameter) if e1.Orientation == 'Reversed': p = p1 p1 = p2 p2 = p if e2.Orientation == 'Reversed': p = p3 p3 = p4 p4 = p v1 = p2 - p1 v2 = p3 - p1 n1 = v1.cross(v2) v3 = p3 - p4 v4 = p2 - p4 n2 = v3.cross(v4) if (n1.dot(n2) < 0): e = e2.copy() e.reverse() return (Part.makeRuledSurface(e1, e)) else: return (Part.makeRuledSurface(e1, e2))
def ruled_surface(e1, e2): """creates a ruled surface between 2 edges, with automatic orientation.""" if not same_direction(e1, e2): e = e2.copy() e.reverse() return Part.makeRuledSurface(e1, e) else: return Part.makeRuledSurface(e1, e2)
def execute(self, obj): c1, c2 = self.get_curves(obj) nc1, nc2 = rp.reparametrize(c1, c2, num=obj.Samples, smooth_start=obj.SmoothingFactorStart, smooth_end=obj.SmoothingFactorEnd, method=obj.Method ) #com = Part.Compound([nc1.toShape(), nc2.toShape()]) rs = Part.makeRuledSurface(nc1.toShape(), nc2.toShape()) if isinstance(rs, Part.Face) and rs.isValid(): obj.Shape = rs
def makeRuledSurface(cls, edgeOrWire1, edgeOrWire2, dist=None): """ 'makeRuledSurface(Edge|Wire,Edge|Wire) -- Make a ruled surface Create a ruled surface out of two edges or wires. If wires are used then these must have the same """ return Shape.cast(FreeCADPart.makeRuledSurface(edgeOrWire1.wrapped, edgeOrWire2.wrapped))
def ruledSurface(self): if isinstance(self.edge1,Part.Edge) and isinstance(self.edge2,Part.Edge): self.ruled = Part.makeRuledSurface(self.edge1, self.edge2) self.rail1 = self.ruled.Edges[0] self.rail2 = self.ruled.Edges[2] self.u0 = self.ruled.ParameterRange[0] self.u1 = self.ruled.ParameterRange[1]
def makeRuledSurface(cls, edgeOrWire1, edgeOrWire2, dist=None): """ 'makeRuledSurface(Edge|Wire,Edge|Wire) -- Make a ruled surface Create a ruled surface out of two edges or wires. If wires are used then these must have the same """ return Shape.cast(FreeCADPart.makeRuledSurface(edgeOrWire1.obj, edgeOrWire2.obj, dist))
def flat_cylinder_surface(face, in_place=False): """ flat_face = flat_cylinder_surface(face, in_place=False) Creates a flat nurbs surface from input cylindrical face, with same parametrization. If in_place is True, the surface is located at the seam edge of the face. """ u0, u1, v0, v1 = get_finite_surface_bounds(face) c1 = face.Surface.uIso(u0) # seam line e1 = c1.toShape(v0, v1) l1 = e1.Length c2 = face.Surface.vIso(v0) # circle e2 = c2.toShape(u0, u1) l2 = e2.Length if in_place: t1 = c2.tangent(c2.FirstParameter)[0] e3 = e1.copy() e3.translate(t1 * l2) rs = Part.makeRuledSurface(e1, e3) bs = rs.Surface bs.exchangeUV() else: bs = Part.BSplineSurface() bs.setPole(1, 1, vec3(v0, 0, 0)) bs.setPole(1, 2, vec3(v1, 0, 0)) bs.setPole(2, 1, vec3(v0, l2, 0)) bs.setPole(2, 2, vec3(v1, l2, 0)) bs.setUKnots([0, 2 * pi]) bs.setVKnots([v0, v1]) return bs
def flat_cone_surface(face, in_place=False): """ flat_face = flat_cone_surface(face, in_place=False) Creates a flat nurbs surface from input conical face, with same parametrization. If in_place is True, the surface is located at the seam edge of the face. """ u0, u1, v0, v1 = get_finite_surface_bounds(face) seam = face.Surface.uIso(u0) p1 = seam.value(v0) p2 = seam.value(v1) radius1 = face.Surface.Apex.distanceToPoint(p1) radius2 = face.Surface.Apex.distanceToPoint(p2) t = seam.tangent(v0)[0] normal = -t.cross(face.Surface.Axis.cross(t)) c1 = Part.Circle(face.Surface.Apex, normal, radius1) c2 = Part.Circle(face.Surface.Apex, normal, radius2) ci1 = face.Surface.vIso(v0) ci2 = face.Surface.vIso(v1) fp1 = c1.parameter(p1) fp2 = c2.parameter(p2) lp1 = c1.parameterAtDistance(ci1.length(), fp1) lp2 = c2.parameterAtDistance(ci2.length(), fp2) if not in_place: c1 = Part.Circle(vec3(0, 0, 0), vec3(0, 0, 1), radius1) c2 = Part.Circle(vec3(0, 0, 0), vec3(0, 0, 1), radius2) else: c1.Axis = -c1.Axis c2.Axis = -c2.Axis ce1 = c1.toShape(fp1, lp1) ce2 = c2.toShape(fp2, lp2) rs = Part.makeRuledSurface(ce1, ce2) bs = rs.Surface bs.setUKnots([0, 2 * pi]) bs.setVKnots([v0, v1]) return bs
def ruledSurface(self): if isinstance(self.edge1, Part.Edge) and isinstance( self.edge2, Part.Edge): self.ruled = Part.makeRuledSurface(self.edge1, self.edge2) self.rail1 = self.ruled.Edges[0] self.rail2 = self.ruled.Edges[2] self.u0 = self.ruled.ParameterRange[0] self.u1 = self.ruled.ParameterRange[1]
def extrudeLinearWithRotation(cls, outerWire, innerWires, vecCenter, vecNormal, angleDegrees): """ Creates a 'twisted prism' by extruding, while simultaneously rotating around the extrusion vector. Though the signature may appear to be similar enough to extrudeLinear to merit combining them, the construction methods used here are different enough that they should be separate. At a high level, the steps followed are: (1) accept a set of wires (2) create another set of wires like this one, but which are transformed and rotated (3) create a ruledSurface between the sets of wires (4) create a shell and compute the resulting object :param outerWire: the outermost wire, a cad.Wire :param innerWires: a list of inner wires, a list of cad.Wire :param vecCenter: the center point about which to rotate. the axis of rotation is defined by vecNormal, located at vecCenter. ( a cad.Vector ) :param vecNormal: a vector along which to extrude the wires ( a cad.Vector ) :param angleDegrees: the angle to rotate through while extruding :return: a cad.Solid object """ # from this point down we are dealing with FreeCAD wires not cad.wires startWires = [outerWire.wrapped] + [i.wrapped for i in innerWires] endWires = [] p1 = vecCenter.wrapped p2 = vecCenter.add(vecNormal).wrapped # make translated and rotated copy of each wire for w in startWires: w2 = w.copy() w2.translate(vecNormal.wrapped) w2.rotate(p1, p2, angleDegrees) endWires.append(w2) # make a ruled surface for each set of wires sides = [] for w1, w2 in zip(startWires, endWires): rs = FreeCADPart.makeRuledSurface(w1, w2) sides.append(rs) #make faces for the top and bottom startFace = FreeCADPart.Face(startWires) endFace = FreeCADPart.Face(endWires) startFace.validate() endFace.validate() #collect all the faces from the sides faceList = [startFace] for s in sides: faceList.extend(s.Faces) faceList.append(endFace) shell = FreeCADPart.makeShell(faceList) solid = FreeCADPart.makeSolid(shell) return Shape.cast(solid)
def execute(self, obj): pl = obj.Placement c1 = Part.Circle() c1.Radius = obj.OutDiameter.Value c2 = Part.Circle() c2.Radius = obj.OutDiameter.Value - 2 * obj.Thickness.Value cs1 = c1.toShape() cs2 = c2.toShape() p = Part.makeRuledSurface(cs2, cs1) obj.Shape = p obj.Placement = pl
def execute(self,obj): pl = obj.Placement c1=Part.Circle() c1.Radius=obj.OutDiameter.Value c2=Part.Circle() c2.Radius=obj.OutDiameter.Value-2*obj.Thickness.Value cs1=c1.toShape() cs2=c2.toShape() p=Part.makeRuledSurface(cs2,cs1) obj.Shape = p obj.Placement = pl
def execute(self, obj): import Part pl = obj.Placement c1 = Part.Circle() c1.Radius = obj.OutDiameter.Value / 2 c2 = Part.Circle() c2.Radius = obj.OutDiameter.Value / 2 - obj.Thickness.Value cs1 = c1.toShape() cs2 = c2.toShape() p = Part.makeRuledSurface(cs2, cs1) p.reverse() obj.Shape = p obj.Placement = pl
def execute(self,obj): import Part pl = obj.Placement c1=Part.Circle() c1.Radius=obj.OutDiameter.Value/2 c2=Part.Circle() c2.Radius=obj.OutDiameter.Value/2-obj.Thickness.Value cs1=c1.toShape() cs2=c2.toShape() p=Part.makeRuledSurface(cs2,cs1) p.reverse() obj.Shape = p obj.Placement = pl
def make_solid(self, face1, face2): if self.flip_face1: face1.face.reverse() if self.flip_face2: face2.face.reverse() edges1 = face1.face.OuterWire.Edges edges2 = face2.face.OuterWire.Edges n1 = len(edges1) n2 = len(edges2) if n1 != n2: raise Exception( f"Faces have different number of edges: {n1} != {n2}") fc_sides = [] sv_sides = [] edges1 = reverse_edges(edges1, reverse=self.reverse1, flip=self.flip1) edges2 = reverse_edges(edges2, reverse=self.reverse2, flip=self.flip2) edges1, edges2 = reorder(edges1, edges2) for edge1, edge2 in zip(edges1, edges2): side = Part.makeRuledSurface(edge1, edge2) sv_side = SvFreeCadNurbsSurface(side.Surface, face=side) fc_sides.append(side) sv_sides.append(sv_side) shell = Part.makeShell([face1.face, face2.face] + fc_sides) lst = [face1.face, face2.face] + fc_sides sh = lst[0].fuse(lst[1:]) solid = Part.makeSolid(sh) if not solid.isValid(): self.debug("Resulting solid is not valid!") if not solid.fix(self.precision, self.precision, self.precision): message = "Solid is not valid, and is not possible to fix" if self.validate: raise Exception(message) else: self.error(message) return solid
Base.Vector(x[0], x[1], x[2]) for x in numpy.vstack((intradosPtsInterp[LEidx::-1], extradosPtsInterp[1:LEidx])) ])) TELines.append( Part.makePolygon([ intradosInterp.Vertexes[-1].Point, extradosInterp.Vertexes[-1].Point ])) print("Creating surfaces") ### LE SURFACE LESurfaces = [] for i in range(2, len(LELines[:-1])): #Start from airfoils, not cylinders LESurfaces.append(Part.makeRuledSurface(LELines[i], LELines[i + 1])) LE = Part.Compound(LESurfaces) #LE=Part.makeLoft(LELines) Part.show(LE) ##### EXTRADOS SURFACE extradosSurfaces = [] for i in range(len(extradosLine[:-1])): extradosSurfaces.append( Part.makeRuledSurface(extradosLine[i], extradosLine[i + 1])) extrados = Part.Compound(extradosSurfaces) #extrados=Part.makeLoft(extradosLine) #Part.show(extrados)
def accept(self): ActiveDocument = FreeCAD.ActiveDocument filename = self.form.filename.text() symmetric = self.form.symmetric.isChecked() chine_count = self.form.chine_count.value() keel_width = [self.form.keel_width.value()] if not os.path.exists(filename): return def tonum(x): if isinstance(x, float): return x try: x = x.strip() return float(x) except: return None def tonumarr(x): return [tonum(y) for y in x] with open(filename, 'r') as f: lines = [x.split(',')[1:] for x in f] station_names = lines[0] x = lines[1] sheer_height = lines[2] sheer_x = lines[3] # Apart from the chines, there are six rows: # - Station names # - Station distance from stern # - Sheer height # - Sheer x # - Rabbet height # - Rabbet x # - Keel height # - Keel x # - Sheer half-width # Each height or width row has a second row below it. If a column of this second row # is not empty, it means that the corresponding poiot is a corner point, rather than # a smooth B-spline point. chine_height = lines[4:2 * chine_count + 4:2] chine_x = lines[5:2 * chine_count + 5:2] rabbet_height = lines[2 * chine_count + 4] rabbet_x = lines[2 * chine_count + 5] keel_height = lines[2 * chine_count + 6] keel_x = lines[2 * chine_count + 7] sheer_width = lines[2 * chine_count + 8] chine_width = lines[2 * chine_count + 9:] print('\n'.join(str(x) for x in [keel_height, keel_x])) print(keel_width) keel_width = keel_width * len(station_names) print(keel_width) def end_tangent(pt, pt1, t): diff = pt - pt1 angle = diff.getAngle(t) axis = diff.cross(t) rot = FreeCAD.Rotation(axis, -angle) return rot.multVec(-diff) * (t.Length / diff.Length) def trivial_tangent(pt1, pt2): return pt1 - pt2 def middle_tangent(pt_prev, pt, pt_next): a = pt_prev - pt b = pt_next - pt tangent = (a + b) / 2 axis = a.cross(b) rot = FreeCAD.Rotation(axis, 90) return rot.multVec(tangent) def tangents(pts, corner): assert len(pts) == len(corner) assert len(pts) > 1 if len(pts) == 2: return [pts[1] - pts[0], pts[0] - pts[1]] calc_tangents = [None] * len(pts) non_none_pts = (item for item in pts if item is not None) first = next(non_none_pts) second = next(non_none_pts) prev = first prev_tangent = None last_pt_index = next( reversed([ index for index, item in enumerate(pts) if item is not None ])) for ii in range(1, last_pt_index - 1): if pts[ii] is None: continue pt = pts[ii] nxt = next(item for item in pts[ii + 1:] if item is not None) calc_tangents[ii] = middle_tangent(prev, pt, nxt) prev = pt prev_tangent = calc_tangents[ii] second_tangent = [ t for pt, t in zip(pts, calc_tangents) if pt is not None ][1] calc_tangents[0] = end_tangent(first, second, second_tangent) calc_tangents[last_pt_index] = end_tangent(pts[last_pt_index], prev, prev_tangent) return calc_tangents def make_part(x, y, z, corner): print('Part') x, y, z = tonumarr(x), tonumarr(y), tonumarr(z) print(x, y, z) vertices = [ FreeCAD.Vector(a, b, c) if (a is not None and b is not None and c is not None) else None for a, b, c in zip(x, y, z) ] print(vertices) segments = [] segment = [] segment_corners = [] overall_tangents = tangents(vertices, corner) first_tangent = None for vertex, c, t in zip(vertices, corner, overall_tangents): if vertex is None: continue segment.append(vertex) segment_corners.append(c) if c is not None and c == 'x': curve = Part.BSplineCurve() ts = tangents(segment, segment_corners) if first_tangent: ts[0] = first_tangent curve.interpolate(segment, Tangents=ts) segments.append(curve) segment = [vertex] segment_corners = [c] first_tangent = None if c is not None and c == 'y': curve = Part.BSplineCurve() ts = tangents(segment, segment_corners) ts[-1] = t if first_tangent: ts[0] = first_tangent curve.interpolate(segment, Tangents=ts) segments.append(curve) segment = [vertex] segment_corners = [c] first_tangent = t if (len(segment) > 0): curve = Part.BSplineCurve() curve.interpolate(segment) segments.append(curve) print('\n'.join(str(s) for s in segments)) shape = Part.makeCompound([x.toShape() for x in segments]) part = ActiveDocument.addObject('Part::Feature', 'Feature') part.Shape = shape return part hull = ActiveDocument.addObject("App::Part", "Hull") ActiveDocument.Tip = hull print(', '.join( str(x) for x in (x[0], sheer_width[0], sheer_height[0], sheer_x[0]))) sheer = make_part(x, sheer_width, sheer_height, sheer_x) chines = [ make_part(x, y, z, c) for y, z, c in zip(chine_width, chine_height, chine_x) ] rabbet = make_part(x, keel_width, rabbet_height, rabbet_x) keel = make_part(x, keel_width, keel_height, keel_x) sheer.Label = "Sheer" hull.addObject(sheer) for i, chine in enumerate(chines): chine.Label = "Chine{}".format(i) hull.addObject(chine) rabbet.Label = "Rabbet" hull.addObject(rabbet) keel.Label = "Keel" hull.addObject(keel) surf = Part.makeRuledSurface(sheer.Shape, chine.Shape)
def execute(self, obj): def error(msg): func_name = "{} (Sketch_On_Surface) : ".format(obj.Label) FreeCAD.Console.PrintError(func_name + msg + "\n") if not obj.Sketch: error("No Sketch attached") return skedges = [] for i in obj.Sketch.Geometry: if i.Construction and obj.ConstructionBounds: skedges.append(i.toShape()) elif not i.Construction and not obj.ConstructionBounds: skedges.append(i.toShape()) #else: #debug("toShape() error, ignoring geometry") comp = Part.Compound(skedges) bb = comp.BoundBox u0, u1, v0, v1 = (bb.XMin, bb.XMax, bb.YMin, bb.YMax) debug("Sketch bounds = {}".format((u0, u1, v0, v1))) try: n = eval(obj.Sketch.Support[0][1][0].lstrip('Face')) face = obj.Sketch.Support[0][0].Shape.Faces[n - 1] #face.Placement = obj.Sketch.Support[0][0].getGlobalPlacement() except (IndexError, AttributeError, SyntaxError) as e: error("Failed to get the face support of the sketch\n") return debug("Target face bounds = {}".format(face.ParameterRange)) if obj.ReverseU: u0, u1 = u1, u0 if obj.ReverseV: v0, v1 = v1, v0 pts = [[FreeCAD.Vector(u0, v0, 0), FreeCAD.Vector(u0, v1, 0)], [FreeCAD.Vector(u1, v0, 0), FreeCAD.Vector(u1, v1, 0)]] bs = stretched_plane(pts, face.ParameterRange, 10.0) quad = bs.toShape() quad.Placement = obj.Sketch.getGlobalPlacement() imput_shapes = [obj.Sketch.Shape] + [o.Shape for o in obj.ExtraObjects] shapes_1 = [] shapes_2 = [] if (obj.Offset == 0): shapes_1 = self.map_shapelist(imput_shapes, quad, face, obj.FillFaces) else: f1 = face.makeOffsetShape(obj.Offset, 1e-3) shapes_1 = self.map_shapelist(imput_shapes, quad, f1.Face1, obj.FillFaces) if (obj.Thickness == 0): if shapes_1: obj.Shape = Part.Compound(shapes_1) return else: f2 = face.makeOffsetShape(obj.Offset + obj.Thickness, 1e-3) shapes_2 = self.map_shapelist(imput_shapes, quad, f2.Face1, obj.FillFaces) if not obj.FillExtrusion: if shapes_1 or shapes_2: obj.Shape = Part.Compound(shapes_1 + shapes_2) return else: shapes = [] for i in range(len(shapes_1)): if isinstance(shapes_1[i], Part.Face): faces = shapes_1[i].Faces + shapes_2[i].Faces #error_wires = [] for j in range(len(shapes_1[i].Edges)): if obj.FillFaces and shapes_1[i].Edges[j].isSeam( shapes_1[i]): continue ruled = Part.makeRuledSurface( shapes_1[i].Edges[j], shapes_2[i].Edges[j]) faces.append(ruled) #try: #face_is_closed = False #for ed in shapes_1[i].Wires[j].Edges: #if ed.isSeam(shapes_1[i]): #face_is_closed = True #debug("closed face detected") #loft = Part.makeLoft([shapes_1[i].Wires[j], shapes_2[i].Wires[j]], False, True, face_is_closed, 5) #faces.extend(loft.Faces) #except Part.OCCError: ##error_wires.extend([shapes_1[i].Wires[j], shapes_2[i].Wires[j]]) #FreeCAD.Console.PrintError("Sketch on surface : failed to create loft face ({},{})".format(i,j)) try: shell = Part.Shell(faces) shell.sewShape() solid = Part.Solid(shell) shapes.append(solid) except Part.OCCError: FreeCAD.Console.PrintWarning( "Sketch on surface : failed to create solid #{}.\n" .format(i + 1)) shapes.extend(faces) else: ruled = Part.makeRuledSurface(shapes_1[i].Wires[0], shapes_2[i].Wires[0]) shapes.append(ruled) #shapes.append(quad) if shapes: if len(shapes) == 1: obj.Shape = shapes[0] elif len(shapes) > 1: obj.Shape = Part.Compound(shapes)
def aa(): #-------------------- kann weg/reuse otherwhere if 1: pass else: ss=Part.sortEdges(col) poles=[] polesseg=[] for w in ss[0]: wn=w.toNurbs() pls=wn.Edge1.Curve.getPoles() if len(polesseg)>0: if (pls[0]- polesseg[-1][-1]).Length<0.001: pass else: pls.reverse() polesseg += [pls] poles += pls degA=self.getData("degree") ls=int(len(polesseg)/2) poles=[] k=self.getData("tangentForce") pfak=degA pfak=0 # fuer weiche uebergaenge for i in range(ls): ll= (polesseg[2*i][0]-polesseg[2*i][1]).Length k *= 0.1*ll poles += [ polesseg[2*i][0]]*pfak try: poles += [ polesseg[2*i][0] + (polesseg[2*i][0]- polesseg[2*i-1][-2]).normalize()*k, polesseg[2*i][1] + (polesseg[2*i][1] -polesseg[2*i+1][1]).normalize()*k, ] except: say("no tangantes possible") poles += [ polesseg[2*i][0] + (polesseg[2*i][0]- polesseg[2*i-1][-2]), polesseg[2*i][1] + (polesseg[2*i][1] -polesseg[2*i+1][1]), ] pass poles += [polesseg[2*i][1]]*pfak poles +=polesseg[2*i+1] sh=Part.makePolygon(poles) sf=Part.BSplineCurve() poles=np.array(poles) (countA,_)=poles.shape multA=[degA+1]+[1]*(countA-1-degA)+[degA+1] knotA=range(len(multA)) sf=Part.BSplineCurve() n=self.getData("rotateAxis") poles2=np.concatenate([poles[n:],poles[:n]]);poles=poles2 sf.buildFromPolesMultsKnots(poles,multA,knotA,False,degA) sh=sf.toShape() if 0 and self.getData("createFace"): t=len(multA)//3-1 sf1=sf.copy() sf2=sf.copy() sf3=sf.copy() sf2.segment(0,t) sf3.segment(t,2*t) sf1.segment(2*t,len(multA)-1) sh=Part.Compound([sf2.toShape(),sf3.toShape(),sf1.toShape()]) Part.show(sh) tt=FreeCAD.ActiveDocument.ActiveObject surf=FreeCAD.ActiveDocument.addObject("Surface::GeomFillSurface","Surface") surf.BoundaryList=[(tt, ('Edge1', 'Edge2', 'Edge3'))] FreeCAD.ActiveDocument.recompute(None,True,True) if self.getData("createFace"): t=len(multA)//2 sf1=sf.copy() sf2=sf.copy() sf2.segment(0,t) sf1.segment(t,len(multA)-1) sh=Part.Compound([sf2.toShape(),sf1.toShape()]) e2=sf1.toShape().Edge1 e2.reverse() sh=Part.makeRuledSurface(sf2.toShape().Edge1,e2) self.setPinObject("Shape_out",sh)
def execute(self, obj): l = obj.Height rf = obj.HeightRandom f = obj.Face[0].getSubObject(obj.Face[1][0]) face = Part.Face (f) (umin, umax, vmin, vmax) = face.ParameterRange # print (umin,umax,vmin,vmax) nbU = obj.U nbV = obj.V nbptsU = nbU + 1 nbptsV = nbV + 1 comp = 0 lattice = [[0] * nbptsV for j in range(nbptsU)] #tableau coordonnées des points shapes = [] i = j = 0 for u in [umin + x * (umax-umin)/nbU for x in range(nbptsU)]: for v in [vmin + x * (vmax-vmin)/nbV for x in range(nbptsV)]: lattice[i][j] = face.valueAt(u,v) j += 1 j = 0 i += 1 if obj.Style == "Points" : if l: for i in range (nbptsU): for j in range(nbptsV): pts2 = lattice[i][j]+face.normalAt(*face.Surface.parameter(lattice[i][j]))*(l+rf*random.random()) shapes.append (Part.makeLine(lattice[i][j],pts2)) else: for i in range (nbptsU): for j in range(nbptsV): shapes.append(Part.Vertex(lattice[i][j])) if obj.Style == "Squares" or obj.Style == "Squares Streched": for i in range (nbU): for j in range(nbV): p1 = lattice[i][j] p2 = lattice[i][j+1] p3 = lattice[i+1][j] p4 = lattice[i+1][j+1] w1 = Part.makeLine (p1,p2) w2 = Part.makeLine (p3,p4) lf = Part.makeRuledSurface (w1,w2) # carreau de base if obj.Style == "Squares" and l: g = lf.CenterOfMass v = -lf.normalAt(*lf.Surface.parameter(g))*(l+rf*random.random()) ps = g + v # point sommet if obj.Sharp: line1 = Part.makeLine (p1,ps) line2 = Part.makeLine (p2,ps) rs1 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p2,ps) line2 = Part.makeLine (p4,ps) rs2 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p4,ps) line2 = Part.makeLine (p3,ps) rs3 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p3,ps) line2 = Part.makeLine (p1,ps) rs4 = Part.makeRuledSurface (line1,line2) shell = Part.Shell(lf.Faces+rs1.Faces+rs2.Faces+rs3.Faces+rs4.Faces) shell.sewShape() solid = Part.Solid(shell) shapes.append(solid) else: shapes.append(lf.extrude(v)) if obj.Style == "Squares Streched" and l: haz = rf*random.random() q1 = p1+face.normalAt(*face.Surface.parameter(p1))*(l+haz) q2 = p2+face.normalAt(*face.Surface.parameter(p2))*(l+haz) q3 = p3+face.normalAt(*face.Surface.parameter(p3))*(l+haz) q4 = p4+face.normalAt(*face.Surface.parameter(p4))*(l+haz) poly1 = Part.makePolygon ([p1,p2,p4,p3,p1]) poly2 = Part.makePolygon ([q1,q2,q4,q3,q1]) tour = Part.makeLoft ([poly1,poly2]) line1 = Part.makeLine (q1,q2) line2 = Part.makeLine (q3,q4) line3 = Part.makeLine (p1,p2) line4 = Part.makeLine (p3,p4) rs1 = Part.makeRuledSurface (line1,line2) rs2 = Part.makeRuledSurface (line3,line4) shell = Part.Shell(tour.Faces+rs1.Faces+rs2.Faces) shell.sewShape() solid = Part.Solid(shell) shapes.append(solid) else: shapes.append(lf) if obj.Style == "Diamonds": if nbU%2 == 0 and nbV%2 == 0: # check if U and V are even: for i in range(0,nbU,2): for j in range(0,nbV,2): p1 = lattice[i+1][j] p2 = lattice[i][j+1] p3 = lattice[i+2][j+1] p4 = lattice[i+1][j+2] w1 = Part.makeLine (p1,p2) w2 = Part.makeLine (p3,p4) lf = Part.makeRuledSurface (w1,w2) if l and obj.Sharp: pc = lattice[i+1][j+1] v = pc+lf.normalAt(*lf.Surface.parameter(pc))*(-l+rf*random.random()) line1 = Part.makeLine (p1,p2) line2 = Part.makeLine (p1,v) rs1 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p2,p4) line2 = Part.makeLine (p2,v) rs2 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p1,p3) line2 = Part.makeLine (p1,v) rs3 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p3,p4) line2 = Part.makeLine (v,p4) rs4 = Part.makeRuledSurface (line1,line2) shell = Part.Shell(lf.Faces+rs1.Faces+rs2.Faces+rs3.Faces+rs4.Faces) shell.sewShape() solid = Part.Solid(shell) shapes.append(solid) if l and not obj.Sharp: p1 = lattice[i+1][j] p2 = lattice[i][j+1] p3 = lattice[i+1][j+2] p4 = lattice[i+2][j+1] L1 = Part.makeLine (p1,p2) L2 = Part.makeLine (p2,p3) L3 = Part.makeLine (p3,p4) L4 = Part.makeLine (p4,p1) diams1 = Part.Wire([L1,L2,L3,L4]) p1_2 = p1+face.normalAt(*face.Surface.parameter(p1))*(l+rf*random.random()) p2_2 = p2+face.normalAt(*face.Surface.parameter(p2))*(l+rf*random.random()) p3_2 = p3+face.normalAt(*face.Surface.parameter(p3))*(l+rf*random.random()) p4_2 = p4+face.normalAt(*face.Surface.parameter(p4))*(l+rf*random.random()) L1 = Part.makeLine (p1_2,p2_2) L2 = Part.makeLine (p2_2,p3_2) L3 = Part.makeLine (p3_2,p4_2) L4 = Part.makeLine (p4_2,p1_2) diams2 = Part.Wire([L1,L2,L3,L4]) cotes = Part.makeLoft([diams1,diams2]) L3 = Part.makeLine (p4_2,p3_2) haut = Part.makeRuledSurface (L1,L3) if obj.Solid: shell = Part.Shell(haut.Faces+cotes.Faces+lf.Faces) shell.sewShape() diams = Part.Solid(shell) else : diams = Part.makeLoft([diams1,diams2],False,True) shapes.append(diams) else: shapes.append(lf) else: print ("U and V must a multiple of 2") if obj.Style == "Small Squares": if nbU%2 == 0 and nbV%2 == 0: for i in range(0,nbU,2): for j in range(0,nbV,2): p1 = lattice[i+1][j+1] p2 = lattice[i+1][j+2] p3 = lattice[i+2][j+2] p4 = lattice[i+2][j+1] w1 = Part.makeLine (p1,p2) w2 = Part.makeLine (p4,p3) lf = Part.makeRuledSurface (w1,w2) g = lf.CenterOfMass v = -lf.normalAt(*lf.Surface.parameter(g))*(l+rf*random.random()) ps = g+v if l!=0 and obj.Sharp: line1 = Part.makeLine (p1,p2) line2 = Part.makeLine (p1,ps) rs1 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p2,p3) line2 = Part.makeLine (p2,ps) rs2 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p1,p4) line2 = Part.makeLine (p1,ps) rs3 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p3,p4) line2 = Part.makeLine (ps,p4) rs4 = Part.makeRuledSurface (line1,line2) shell = Part.Shell(lf.Faces+rs1.Faces+rs2.Faces+rs3.Faces+rs4.Faces) shell.sewShape() solid = Part.Solid(shell) shapes.append(solid) if l and not obj.Sharp: shapes.append(lf.extrude(v)) else: shapes.append(lf) else: print ("U and V must be a multiple of 2") if obj.Style == "PedestriansWalk": if nbU%3 == 0 and nbV%6 == 0: for i in range(0,nbU,3): for j in range(0,nbV,6): p1 = lattice[i+1][j+1] p2 = lattice[i+1][j+5] p3 = lattice[i+2][j+5] p4 = lattice[i+2][j+1] w1 = Part.makeLine (p1,p2) w2 = Part.makeLine (p4,p3) lf = Part.makeRuledSurface (w1,w2) g = lf.CenterOfMass v = -lf.normalAt(*lf.Surface.parameter(g))*(l+rf*random.random()) ps = g+v if l and obj.Sharp: line1 = Part.makeLine (p1,p2) line2 = Part.makeLine (p1,ps) rs1 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p2,p3) line2 = Part.makeLine (p2,ps) rs2 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p1,p4) line2 = Part.makeLine (p1,ps) rs3 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p3,p4) line2 = Part.makeLine (ps,p4) rs4 = Part.makeRuledSurface (line1,line2) shell = Part.Shell(lf.Faces+rs1.Faces+rs2.Faces+rs3.Faces+rs4.Faces) shell.sewShape() solid = Part.Solid(shell) shapes.append(solid) if l and not obj.Sharp: shapes.append(lf.extrude(v)) else: shapes.append(lf) else: print ("U and V must be a multiple of 6") if obj.Style == "Checkers": if nbU%2 == 0 and nbV%2 == 0: for i in range(0,nbU,1): d = 0 if i%2 !=0 : d = 1 for j in range(0,nbV-d,2): p1 = lattice[i][j+d] p2 = lattice[i+1][j+d] p3 = lattice[i][j+1+d] p4 = lattice[i+1][j+1+d] w1 = Part.makeLine (p1,p2) w2 = Part.makeLine (p3,p4) lf = Part.makeRuledSurface (w1,w2) #carreau de base if l: g = lf.CenterOfMass v = lf.normalAt(*lf.Surface.parameter(g))*(l+rf*random.random()) ps = g + v # point sommet if obj.Sharp: line1 = Part.makeLine (p1,ps) line2 = Part.makeLine (p2,ps) rs1 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p2,ps) line2 = Part.makeLine (p4,ps) rs2 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p4,ps) line2 = Part.makeLine (p3,ps) rs3 = Part.makeRuledSurface (line1,line2) line1 = Part.makeLine (p3,ps) line2 = Part.makeLine (p1,ps) rs4 = Part.makeRuledSurface (line1,line2) shell = Part.Shell(lf.Faces+rs1.Faces+rs2.Faces+rs3.Faces+rs4.Faces) shell.sewShape() solid = Part.Solid(shell) shapes.append(solid) else: shapes.append(lf.extrude(v)) else: shapes.append(lf) else: print ("U and V must be a multiple of 2") if obj.Style == "Hatch": for i in range(0,nbU): for j in range(0,nbV): p1 = lattice[i][j] p2 = lattice[i+1][j+1] L1 = Part.makeLine(p1, p2) seg1 = Part.Wire([L1]) rand = rf*random.random() if l: p1_2 = p1+f.normalAt(*f.Surface.parameter(p1))*(l+rand) p2_2 = p2+f.normalAt(*f.Surface.parameter(p2))*(l+rand) L2 = Part.makeLine(p1_2, p2_2) seg2 = Part.Wire([L2]) loft = Part.makeLoft([seg1,seg2]) shapes.append(loft) else : shapes.append(seg1) if obj.Style == "Bubble": if nbU%2 == 0 and nbV%2 == 0: # check if U and V are even: nbU=nbV=2 for i in range (0,nbU,2): for j in range(0,nbV,2): pts=[] # pts.append(lattice[i][j+1]) # pts.append(lattice[i+1][j+2]) # pts.append(lattice[i+2][j+1]) # pts.append(lattice[i+1][j]) pts.append(lattice[i+1][j]) pts.append(lattice[i+2][j+1]) pts.append(lattice[i+1][j+2]) pts.append(lattice[i][j+1]) curve=Part.BSplineCurve() # curve.increaseDegree(4) curve.interpolate(pts,True) # curve.setPeriodic() # pc = lattice[i+1][j+1] # norm = face.normalAt(*face.Surface.parameter(pc)) print(pts) shapes.append(curve) else: print ("U and V must a multiple of 2") if obj.Style == "Honeycomb": if nbU%3 == 0 and nbV%3 == 0: for i in range(0,nbU,3): for j in range(0,nbV,3): p1 = lattice[i+1][j] p2 = lattice[i][j+1] p3 = lattice[i][j+2] p4 = lattice[i+1][j+3] p5 = lattice[i+2][j+3] p6 = lattice[i+3][j+2] p7 = lattice[i+3][j+1] p8 = lattice[i+2][j] L1 = Part.makeLine(p1, p2) L2 = Part.makeLine(p2, p3) L3 = Part.makeLine(p3, p4) L4 = Part.makeLine(p4, p5) L5 = Part.makeLine(p5, p6) L6 = Part.makeLine(p6, p7) L7 = Part.makeLine(p7, p8) L8 = Part.makeLine(p8, p1) hexa = Part.Wire([L1,L2,L3,L4,L5,L6,L7,L8]) rand = rf*random.random() if l: p1_2 = p1+f.normalAt(*f.Surface.parameter(p1))*(l+rand) p2_2 = p2+f.normalAt(*f.Surface.parameter(p2))*(l+rand) p3_2 = p3+f.normalAt(*f.Surface.parameter(p3))*(l+rand) p4_2 = p4+f.normalAt(*f.Surface.parameter(p4))*(l+rand) p5_2 = p5+f.normalAt(*f.Surface.parameter(p5))*(l+rand) p6_2 = p6+f.normalAt(*f.Surface.parameter(p6))*(l+rand) p7_2 = p7+f.normalAt(*f.Surface.parameter(p7))*(l+rand) p8_2 = p8+f.normalAt(*f.Surface.parameter(p8))*(l+rand) L1 = Part.makeLine(p1_2, p2_2) L2 = Part.makeLine(p2_2, p3_2) L3 = Part.makeLine(p3_2, p4_2) L4 = Part.makeLine(p4_2, p5_2) L5 = Part.makeLine(p5_2, p6_2) L6 = Part.makeLine(p6_2, p7_2) L7 = Part.makeLine(p7_2, p8_2) L8 = Part.makeLine(p8_2, p1_2) hexa2 = Part.Wire([L1,L2,L3,L4,L5,L6,L7,L8]) loft = Part.makeLoft([hexa,hexa2]) shapes.append(loft) else : shapes.append(hexa) else: print ("U and V must be a multiple of 3") if shapes: comp=Part.Compound(shapes) if comp: if obj.Limit: if l!=0: # c = face.valueAt((umax+umin)/2,(vmax+vmin)/2) c = face.CenterOfMass Vup = c+face.normalAt(*face.Surface.parameter(c))*(l*1.1) Vdn = c+face.normalAt(*face.Surface.parameter(c))*(-l*1.1) ShapeFace1 = face.extrude(Vup-c) ShapeFace = ShapeFace1.fuse(face.extrude(Vdn-c)) obj.Shape = comp.common(ShapeFace,0.1) else: obj.Shape = comp.common(face,0.1) else: obj.Shape = comp