def getcenter(lEdges, r): import math rndEdges = lEdges[0:2] rndEdges = Part.__sortEdges__(rndEdges) lVertexes = rndEdges[0].Vertexes + [rndEdges[1].Vertexes[-1]] U1 = lVertexes[0].Point.sub(lVertexes[1].Point) U1.normalize() U2 = lVertexes[2].Point.sub(lVertexes[1].Point) U2.normalize() alpha = U1.getAngle(U2) # Edges have same direction '''if (round(alpha, 0) == 0) or (round(alpha - math.pi, 0) == 0): pt1 = FreeCAD.Vector(U1) x = pt1.x pt1.x = pt1.y pt1.y = -x return rndEdges pointsDirection = lineSelected.discretize(Number=500) # discretize the path line first selection v = pointsDirection[0].sub(pointsDirection[1]) # avec vecteurs 1 et 2 (direction debut ligne) r = App.Rotation(App.Vector(0, 0, 1), v)''' dToCenter = r / math.sin(alpha / 2.0) # dToTangent = (dToCenter ** 2 - r ** 2) ** 0.5 dirVect = U2.add(U1) dirVect.normalize() dirVect.scale(dToCenter, dToCenter, dToCenter) pt1 = lVertexes[1].Point.add(dirVect) pt2 = -1 * pt1 pt2.z = pt1.z print(pt1, " - ", pt2) return [pt1, pt2] # from DRAFT def split_wire(wire, newPoint, edgeIndex): import Draft wire1Points = [] wire2Points = [] print("New Point: ", newPoint) print("edgeIndex: ", edgeIndex) for index, point in enumerate(wire.Points): print("index: ", index, " - point: ", point) if index == edgeIndex: wire1Points.append(point) wire1Points.append(wire.Placement.inverse().multVec(newPoint)) wire2Points.append(newPoint) # wire2Points.append(wire.Placement.multVec(point)) elif index < edgeIndex: wire1Points.append(point) elif index > edgeIndex: wire2Points.append(wire.Placement.multVec(point)) if len(wire1Points) == 1: wire1Points.insert(0, wire.Points[0]) if len(wire2Points) == 1: wire2Points.appen(wire.Points[-1]) wire.Points = wire1Points wire2 = Draft.makeWire(wire2Points, placement=wire.Placement) FreeCAD.ActiveDocument.recompute() wires = [wire, wire2] return sorted(wires, key=lambda obj: obj.Length, reverse=True) def SplitTrench(trench, point): if not trench or not point: return None import Part wire = trench.Base vertex = Part.Vertex(point) '''Find the minimum distance to another shape: - distToShape(shape) -> (dist, vectors, infos) dist is the minimum distance, in mm (float value). vectors is a list of pairs of App.Vector. Each pair corresponds to solution. Example: [(Vector (2.0, -1.0, 2.0), Vector (2.0, 0.0, 2.0)), (Vector (2.0,-1.0, 2.0), Vector (2.0, -1.0, 3.0))] - First vector is a point on self, second vector is a point on s. infos contains additional info on the solutions. It is a list of tuples: (topo1, index1, params1, topo2, index2, params2) - topo1, topo2 are strings identifying type of BREP element: 'Vertex', 'Edge', or 'Face'. - index1, index2 are indexes of the elements (zero-based). - params1, params2 are parameters of internal space of the elements. For vertices, params is None. For edges, params is one float, u. For faces, params is a tuple (u,v). (719762.0578530617, [(Vector (225057.375, 783988.625, 715062.875), Vector (306961.4605149741, 778138.3688035253, 0.0))], [('Vertex', 0, None, 'Edge', 0, 79697.52668425611)]) ''' (dist, vectors, infos) = vertex.distToShape(wire.Shape) if not dist: return None Location = FreeCAD.Vector(vectors[0][1]) if not Location: return None Normal = None edind = 0 if infos[0][3] == 'Vertex': vec = Location.sub(point) Normal = FreeCAD.Vector(vec[1], -vec[0], vec[2]) edind = int(infos[0][4]) - 1 elif infos[0][3] == 'Edge': ed = wire.Shape.Edges[int(dist[2][0][4])] Normal = ed.Vertexes[1].Point.sub(ed.Vertexes[0].Point) edind = int(infos[0][4]) wires = split_wire(wire, Location, edind) trench.Base = wires[0] trench1 = makeTrench(wire[1]) return Location, [trench, trench1], node def JoinTrench(trench1, trench2): if not trench1 or not trench2: return None class CommandSplitTrench: # V1: """Gui command for the Line tool.""" def GetResources(self): """Set icon, menu and tooltip.""" return {'Pixmap': str(os.path.join(DirIcons, "trench.svg")), 'MenuText': "Trench", 'Accel': "C, T", 'ToolTip': "Creates a Trench object from setup dialog."} def IsActive(self): return (not (FreeCAD.ActiveDocument is None) and not (FreeCAD.ActiveDocument.getObject("Trench") is None)) def Activated(self): """Execute when the command is called.""" sel = FreeCADGui.Selection.getSelection() done = False if len(sel) > 0: import Draft for obj in sel: if Draft.getType(obj) == "Wire": FreeCAD.ActiveDocument.openTransaction("Create Trench") makeTrench(obj) FreeCAD.ActiveDocument.commitTransaction() FreeCAD.ActiveDocument.recompute() done = True break if not done: taskd = TrenchTaskPanel() if taskd: FreeCADGui.Control.showDialog(taskd) else: print(" No ha sido posible crear el formulario") class CommandJoinTrench: # V1: """Gui command for the Line tool.""" def GetResources(self): """Set icon, menu and tooltip.""" return {'Pixmap': str(os.path.join(DirIcons, "trenchsplit.svg")), 'MenuText': "Semi-Automatic Trench Generator", 'Accel': "T, S", 'ToolTip': "Creates a Trench object from setup dialog."} def IsActive(self): return (not (FreeCAD.ActiveDocument is None) and not (FreeCAD.ActiveDocument.getObject("Trench") is None)) def Activated(self): """Execute when the command is called.""" semi = semiAutomaticTrench() if FreeCAD.GuiUp: class CommandTrenchGroup: def GetCommands(self): return tuple(['PVPlantSplitTrench', 'PVPlantJoinTrench', ]) def GetResources(self): return {'MenuText': 'Trench operations', 'ToolTip': 'Trench operations' } def IsActive(self): active = not (FreeCAD.ActiveDocument is None) terrain = not (FreeCAD.ActiveDocument.getObject("Terrain") is None) active = active and terrain if terrain: active = active and not (FreeCAD.ActiveDocument.getObject("Terrain").Mesh is None) return active FreeCADGui.addCommand('PVPlantTrench', CommandTrench()) FreeCADGui.addCommand('PVPlantSemiAutomaticTrench', CommandSemiAutomaticTrench()) FreeCADGui.addCommand('Trenches', CommandTrenchGroup())