def circlefrom1Line2Points(edge, p1, p2): """circlefrom1Line2Points(edge, Vector, Vector)""" p1_p2 = edg(p1, p2) s = findIntersection(edge, p1_p2, True, True) if not s: return None s = s[0] v1 = p1.sub(s) v2 = p2.sub(s) projectedDist = math.sqrt(abs(v1.dot(v2))) edgeDir = vec(edge) edgeDir.normalize() projectedCen1 = Vector.add(s, Vector(edgeDir).multiply(projectedDist)) projectedCen2 = Vector.add(s, Vector(edgeDir).multiply(-projectedDist)) perpEdgeDir = edgeDir.cross(Vector(0, 0, 1)) perpCen1 = Vector.add(projectedCen1, perpEdgeDir) perpCen2 = Vector.add(projectedCen2, perpEdgeDir) mid = findMidpoint(p1_p2) x = DraftVecUtils.crossproduct(vec(p1_p2)) x.normalize() perp_mid = Vector.add(mid, x) cen1 = findIntersection(edg(projectedCen1, perpCen1), edg(mid, perp_mid), True, True) cen2 = findIntersection(edg(projectedCen2, perpCen2), edg(mid, perp_mid), True, True) circles = [] if cen1: radius = DraftVecUtils.dist(projectedCen1, cen1[0]) circles.append(Part.Circle(cen1[0], NORM, radius)) if cen2: radius = DraftVecUtils.dist(projectedCen2, cen2[0]) circles.append(Part.Circle(cen2[0], NORM, radius)) if circles: return circles else: return None
def handle_mouse_move_event(self, arg): """Handle the mouse when moving.""" plane = App.DraftWorkingPlane for ghost in self.ghosts: ghost.off() self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) # this is to make sure radius is what you see on screen if self.center and DraftVecUtils.dist(self.point, self.center): viewdelta = DraftVecUtils.project(self.point.sub(self.center), plane.axis) if not DraftVecUtils.isNull(viewdelta): self.point = self.point.add(viewdelta.negative()) if self.extendedCopy: if not gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): self.step = 3 self.finish() if self.step == 0: pass elif self.step == 1: currentrad = DraftVecUtils.dist(self.point, self.center) if currentrad != 0: angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis) else: angle = 0 self.ui.setRadiusValue(math.degrees(angle), unit="Angle") self.firstangle = angle self.ui.radiusValue.setFocus() self.ui.radiusValue.selectAll() elif self.step == 2: currentrad = DraftVecUtils.dist(self.point, self.center) if currentrad != 0: angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis) else: angle = 0 if angle < self.firstangle: sweep = (2 * math.pi - self.firstangle) + angle else: sweep = angle - self.firstangle self.arctrack.setApertureAngle(sweep) for ghost in self.ghosts: ghost.rotate(plane.axis, sweep) ghost.on() self.ui.setRadiusValue(math.degrees(sweep), 'Angle') self.ui.radiusValue.setFocus() self.ui.radiusValue.selectAll() gui_tool_utils.redraw3DView()
def mouseClick(self, event_cb): event = event_cb.getEvent() if event.getButton() == 1: if event.getState() == coin.SoMouseButtonEvent.DOWN: #start point if len(self.points) == 0: self.points.append(self.pt) self.coords.oX.setText(str(round(self.pt[0], 2))) self.coords.oY.setText(str(round(self.pt[1], 2))) self.coords.oZ.setText(str(round(self.pt[2], 2))) self.lastpoint = self.pt #end point elif len(self.points) == 1: # calculate the local vector origInLocalCoords = FreeCAD.DraftWorkingPlane.getLocalCoords( self.points[0]) self.vecInLocalCoords = FreeCAD.DraftWorkingPlane.getLocalCoords( self.pt) self.vecInLocalCoords = self.vecInLocalCoords - origInLocalCoords self.coords.eX.setText( str(round(self.vecInLocalCoords[0], 2))) self.coords.eY.setText( str(round(self.vecInLocalCoords[1], 2))) self.closeEvents() self.points.append(self.pt) FreeCADGui.Snapper.off() #start keyboard events self.callbackKeys = self.curview.addEventCallbackPivy( coin.SoKeyboardEvent.getClassTypeId(), self.keys) self.setWidth( DraftVecUtils.dist(self.points[0], self.points[1])) self.inspoint.rb_1.setChecked(True) self.redraw()
def pointInversion(circle, point): """Return the circle inversion of a point. It will return `None` if the given point is equal to the center of the circle. """ if geomType(circle) != "Circle" or isinstance(point, App.Vector): print("debug: pointInversion bad parameters!") return None cen = circle.Curve.Center rad = circle.Curve.Radius if DraftVecUtils.equals(cen, point): return None # Inverse the distance of the point # dist(cen -> P) = r^2 / dist(cen -> invP) dist = DraftVecUtils.dist(point, cen) invDist = rad**2 / dist invPoint = App.Vector(0, 0, point.z) invPoint.x = cen.x + (point.x - cen.x) * invDist / dist invPoint.y = cen.y + (point.y - cen.y) * invDist / dist return invPoint
def pointInversion(circle, point): """Circle inversion of a point. pointInversion(Circle, Vector) Will calculate the inversed point an return it. If the given point is equal to the center of the circle "None" will be returned. See also: http://en.wikipedia.org/wiki/Inversive_geometry """ if (geomType(circle) == "Circle") and isinstance(point, FreeCAD.Vector): cen = circle.Curve.Center rad = circle.Curve.Radius if DraftVecUtils.equals(cen, point): return None # Inverse the distance of the point # dist(cen -> P) = r^2 / dist(cen -> invP) dist = DraftVecUtils.dist(point, cen) invDist = rad**2 / d invPoint = Vector(0, 0, point.z) invPoint.x = cen.x + (point.x - cen.x) * invDist / dist invPoint.y = cen.y + (point.y - cen.y) * invDist / dist return invPoint else: FreeCAD.Console.PrintMessage("debug: pointInversion bad parameters!\n") return None
def circleInversion(circle, circle2): """ pointInversion(Circle, Circle) Circle inversion of a circle. """ if (geomType(circle) == "Circle") and (geomType(circle2) == "Circle"): cen1 = circle.Curve.Center rad1 = circle.Curve.Radius if DraftVecUtils.equals(cen1, point): return None invCen2 = Inversion(circle, circle2.Curve.Center) pointOnCircle2 = Vector.add(circle2.Curve.Center, Vector(circle2.Curve.Radius, 0, 0)) invPointOnCircle2 = Inversion(circle, pointOnCircle2) return Part.Circle(invCen2, norm, DraftVecUtils.dist(invCen2, invPointOnCircle2)) else: FreeCAD.Console.PrintMessage( "debug: circleInversion bad parameters!\n") return None
def circleInversion(circle, circle2): """Circle inversion of a circle, inverting the center point. Returns the new circle created from the inverted center of circle2. """ if geomType(circle) != "Circle" or geomType(circle2) != "Circle": print("debug: circleInversion bad parameters! Must be circles.") return None cen1 = circle.Curve.Center cen2 = circle2.Curve.Center rad2 = circle2.Curve.Radius if DraftVecUtils.equals(cen1, cen2): return None invCen2 = pointInversion(circle, cen2) pointOnCircle2 = App.Vector.add(cen2, App.Vector(rad2, 0, 0)) invPointOnCircle2 = pointInversion(circle, pointOnCircle2) return Part.Circle(invCen2, NORM, DraftVecUtils.dist(invCen2, invPointOnCircle2))
def findRadicalAxis(circle1, circle2): """Calculate the radical axis of two circles. On the radical axis (also called power line) of two circles any tangents drawn from a point on the axis to both circles have the same length. http://en.wikipedia.org/wiki/Radical_axis http://mathworld.wolfram.com/RadicalLine.html See Also -------- findRadicalCenter """ if (geomType(circle1) == "Circle") and (geomType(circle2) == "Circle"): print("debug: findRadicalAxis bad parameters! Must be circles.") return None if DraftVecUtils.equals(circle1.Curve.Center, circle2.Curve.Center): return None r1 = circle1.Curve.Radius r2 = circle1.Curve.Radius cen1 = circle1.Curve.Center # dist .. the distance from cen1 to cen2. dist = DraftVecUtils.dist(cen1, circle2.Curve.Center) cenDir = cen1.sub(circle2.Curve.Center) cenDir.normalize() # Get the perpedicular vector. perpCenDir = cenDir.cross(App.Vector(0, 0, 1)) perpCenDir.normalize() # J ... The radical center. # K ... The point where the cadical axis crosses the line of cen1->cen2. # k1 ... Distance from cen1 to K. # k2 ... Distance from cen2 to K. # dist = k1 + k2 k1 = (dist + (r1**2 - r2**2) / dist) / 2.0 # k2 = dist - k1 K = App.Vector.add(cen1, cenDir.multiply(k1)) # K_ .. A point somewhere between K and J; actually with a distance # of 1 unit from K. K_ = App.Vector.add(K, perpCenDir) # Original code didn't specify the value of origin nor dir, # so this is a guess: # radicalAxis = Part.LineSegment(K, Vector.add(origin, dir)) origin = App.Vector(0, 0, 0) radicalAxis = Part.LineSegment(K, App.Vector.add(origin, perpCenDir)) if radicalAxis: return radicalAxis else: return None
def circleFromPointLineRadius(point, edge, radius): """Return a list of circles from one point, one edge, and one radius. It calculates up to 2 possible centers. """ dist = findDistance(point, edge, False) center1 = None center2 = None if dist.Length == 0: segment = vec(edge) perpVec = DraftVecUtils.crossproduct(segment) perpVec.normalize() normPoint_c1 = App.Vector(perpVec).multiply(radius) normPoint_c2 = App.Vector(perpVec).multiply(-radius) center1 = point.add(normPoint_c1) center2 = point.add(normPoint_c2) elif dist.Length > 2 * radius: return None elif dist.Length == 2 * radius: normPoint = point.add(findDistance(point, edge, False)) dummy = (normPoint.sub(point)).multiply(0.5) cen = point.add(dummy) circ = Part.Circle(cen, NORM, radius) if circ: return [circ] else: return None else: normPoint = point.add(findDistance(point, edge, False)) normDist = DraftVecUtils.dist(normPoint, point) dist = math.sqrt(radius**2 - (radius - normDist)**2) centerNormVec = DraftVecUtils.scaleTo(point.sub(normPoint), radius) edgeDir = edge.Vertexes[0].Point.sub(normPoint) edgeDir.normalize() center1 = centerNormVec.add( normPoint.add(App.Vector(edgeDir).multiply(dist))) center2 = centerNormVec.add( normPoint.add(App.Vector(edgeDir).multiply(-dist))) circles = [] if center1: circ = Part.Circle(center1, NORM, radius) if circ: circles.append(circ) if center2: circ = Part.Circle(center2, NORM, radius) if circ: circles.append(circ) if circles: return circles else: return None
def set_start_point(self): """Set the starting point of the rotation.""" self.ui.labelRadius.setText(translate("draft", "Rotation")) self.ui.radiusValue.setToolTip(translate("draft", "The amount of rotation you wish to perform.\nThe final angle will be the base angle plus this amount.")) self.rad = DraftVecUtils.dist(self.point, self.center) self.arctrack.on() self.arctrack.setStartPoint(self.point) for ghost in self.ghosts: ghost.on() self.step = 2 _msg(translate("draft", "Pick rotation angle"))
def create(self, structure=None, start=Base.Vector(0, 0, 0), end=Base.Vector(0, 0, 0), isShadow=False): '''create(self, structure=None, startPoint=Base.Vector(0, 0, 0), endPoint=Base.Vector(0, 0, 0), isShadow=False) create the beam structure : copy of an existent beam start : the origin point in global coords end : the end point in global coords isShadow: transparent mode ''' self.points = [start, end] self.isShadow = isShadow self.currentInsPoint = self.points[0] # set length of the beam if not self.orientation == 2: self.length = DraftVecUtils.dist(self.points[0], self.points[1]) # Beam creation if self.structure: self.structure = structure else: if not self.profil: profpoints = [] profpoints.append( FreeCAD.Vector(-self.width / 2, -self.height / 2, 0)) profpoints.append( FreeCAD.Vector(self.width / 2, -self.height / 2, 0)) profpoints.append( FreeCAD.Vector(self.width / 2, self.height / 2, 0)) profpoints.append( FreeCAD.Vector(-self.width / 2, self.height / 2, 0)) self.profil = Draft.makeWire(profpoints, closed=True) self.profil.Label = str(self.width) + "x" + str( self.height) + "_0" #self.structure = Arch.makeStructure(None, self.length, self.width, self.height) self.structure = Arch.makeStructure(self.profil, self.length) self.structure.MoveBase = True #Nodes : nodes .... the dark face if not self.orientation == 2: self.structure.Nodes = [self.points[0], self.points[1]] else: ###TODO pass self.setAttributes() self.setOrientation() self.setRotations() return self
def findRadicalAxis(circle1, circle2): """Calculate the radical axis of two circles. On the radical axis (also called power line) of two circles any tangents drawn from a point on the axis to both circles have the same length. http://en.wikipedia.org/wiki/Radical_axis http://mathworld.wolfram.com/RadicalLine.html @sa findRadicalCenter """ if (geomType(circle1) == "Circle") and (geomType(circle2) == "Circle"): if DraftVecUtils.equals(circle1.Curve.Center, circle2.Curve.Center): return None r1 = circle1.Curve.Radius r2 = circle1.Curve.Radius cen1 = circle1.Curve.Center # dist .. the distance from cen1 to cen2. dist = DraftVecUtils.dist(cen1, circle2.Curve.Center) cenDir = cen1.sub(circle2.Curve.Center) cenDir.normalize() # Get the perpedicular vector. perpCenDir = cenDir.cross(Vector(0, 0, 1)) perpCenDir.normalize() # J ... The radical center. # K ... The point where the cadical axis crosses the line of cen1->cen2. # k1 ... Distance from cen1 to K. # k2 ... Distance from cen2 to K. # dist = k1 + k2 k1 = (dist + (r1 ^ 2 - r2 ^ 2) / dist) / 2.0 #k2 = dist - k1 K = Vector.add(cen1, cenDir.multiply(k1)) # K_ .. A point somewhere between K and J (actually with a distance of 1 unit from K). K_ = Vector, add(K, perpCenDir) radicalAxis = Part.LineSegment(K, Vector.add(origin, dir)) if radicalAxis: return radicalAxis else: return None else: FreeCAD.Console.PrintMessage( "debug: findRadicalAxis bad parameters!\n") return None
def circleFrom2PointsRadius(p1, p2, radius): """Return a list of circles from two points, and one radius. The two points must not be equal. It calculates up to 2 possible centers. """ if DraftVecUtils.equals(p1, p2): return None p1_p2 = Part.LineSegment(p1, p2).toShape() dist_p1p2 = DraftVecUtils.dist(p1, p1) mid = findMidpoint(p1_p2) if dist_p1p2 == 2*radius: circle = Part.Circle(mid, NORM, radius) if circle: return [circle] else: return None _dir = vec(p1_p2) _dir.normalize() perpDir = _dir.cross(App.Vector(0, 0, 1)) perpDir.normalize() dist = math.sqrt(radius**2 - (dist_p1p2 / 2.0)**2) cen1 = App.Vector.add(mid, App.Vector(perpDir).multiply(dist)) cen2 = App.Vector.add(mid, App.Vector(perpDir).multiply(-dist)) circles = [] if cen1: circles.append(Part.Circle(cen1, NORM, radius)) if cen2: circles.append(Part.Circle(cen2, NORM, radius)) if circles: return circles else: return None
def circleFrom2PointsRadius(p1, p2, radius): """circleFrom2PointsRadiust(Vector, Vector, radius)""" if DraftVecUtils.equals(p1, p2): return None p1_p2 = Part.LineSegment(p1, p2).toShape() dist_p1p2 = DraftVecUtils.dist(p1, p1) mid = findMidpoint(p1_p2) if dist_p1p2 == 2 * radius: circle = Part.Circle(mid, NORM, radius) if circle: return [circle] else: return None dir = vec(p1_p2) dir.normalize() perpDir = dir.cross(Vector(0, 0, 1)) perpDir.normalize() dist = math.sqrt(radius**2 - (dist_p1p2 / 2.0)**2) cen1 = Vector.add(mid, Vector(perpDir).multiply(dist)) cen2 = Vector.add(mid, Vector(perpDir).multiply(-dist)) circles = [] if cen1: circles.append(Part.Circle(cen1, NORM, radius)) if cen2: circles.append(Part.Circle(cen2, NORM, radius)) if circles: return circles else: return None
def update(self, point, info): "this function is called by the Snapper when the mouse is moved" if Gui.Control.activeDialog(): if self.direction != "line": if len(self.clicked_points) == 0: final_point = point.add( self.get_final_point(self.direction)) self.tracker.update( anchor_idx=self.anchor_idx, inclination=self.inclination, base_snap_vertex=point, final_snap_vertex=final_point, ) self.tracker.on() elif self.direction == "line": if len(self.clicked_points) == 1: length = DraftVecUtils.dist(self.clicked_points[0], point) self.length_input.setText( App.Units.Quantity(length, App.Units.Length).UserString) self.tracker.update( inclination=self.inclination, anchor_idx=self.anchor_idx, base_snap_vertex=self.clicked_points[0], final_snap_vertex=point, ) self.tracker.on() else: self.tracker.off() else: Gui.Snapper.toggleGrid()
def makeTransaction(self, point=None): """g3d beam makeTransaction""" msg = ["", "----------", "makeTransaction"] msg.append("la direction est : {}".format(str(self.direction))) msg.append("le mode de pattern est : {}".format(str(self.pattern))) msg.append("Détails de la liste des points cliqués :") msg.append("longueur = {}".format(len(self.clicked_points))) for p in self.clicked_points: msg.append(str(p)) print_debug(msg) commands = [] if self.pattern == 'none': transaction_name = "Create G3DBeam from 1 points" command = "freecad.workbench_gespal3d.g3d_beam.makeG3DBeam(" \ + "g3d_profile={}, ".format(str(self.Profile)) \ + "p1={}, ".format(str(DraftVecUtils.tup(self.clicked_points[0],True))) \ + "p2={}, ".format(str(DraftVecUtils.tup(self.clicked_points[1],True))) \ + "anchor={}, ".format(self.anchor_idx) \ + "inclination={}, ".format(self.inclination) \ + ")" commands.append(command) elif self.pattern == 'distribution': transaction_name = "Création d'une répartition de composants." length = DraftVecUtils.dist(self.clicked_points[0], self.clicked_points[2]) space = length / (self.distribution_qty + 1) vec = self.clicked_points[2].sub(self.clicked_points[0]) vec_norm = vec.normalize() vec_axe = vec_norm.multiply(space) p1 = self.clicked_points[0] p2 = self.clicked_points[1] qty = self.distribution_qty if self.distribution_start.isChecked(): p1 = p1.sub(vec_axe) p2 = p2.sub(vec_axe) qty += 1 if self.distribution_end.isChecked(): qty += 1 for distri in range(qty): #if not self.distribution_start.isChecked(): p1 = p1.add(vec_axe) p2 = p2.add(vec_axe) command = "freecad.workbench_gespal3d.g3d_beam.makeG3DBeam(" \ + "g3d_profile={}, ".format(str(self.Profile)) \ + "p1={}, ".format(str(DraftVecUtils.tup(p1, True))) \ + "p2={}, ".format(str(DraftVecUtils.tup(p2, True))) \ + "anchor={}, ".format(self.anchor_idx) \ + "inclination={}, ".format(self.inclination) \ + ")" commands.append(command) elif self.pattern == 'filling': transaction_name = "Création d'un remplissage de composants." length = DraftVecUtils.dist(self.clicked_points[0], self.clicked_points[2]) space = length / (self.distribution_qty + 1) vec = self.clicked_points[2].sub(self.clicked_points[0]) vec_norm = vec.normalize() vec_axe = vec_norm.multiply(space) p1 = self.clicked_points[0] p2 = self.clicked_points[1] for qty in range(self.distribution_qty): p1 = p1.add(vec_axe) p2 = p2.add(vec_axe) command = "freecad.workbench_gespal3d.g3d_beam.makeG3DBeam(" \ + "g3d_profile={}, ".format(str(self.Profile)) \ + "p1={}, ".format(str(DraftVecUtils.tup(p1, True))) \ + "p2={}, ".format(str(DraftVecUtils.tup(p2, True))) \ + "anchor={}, ".format(self.anchor_idx) \ + "inclination={}, ".format(self.inclination) \ + ")" commands.append(command) else: App.Console.PrintWarning("This mode is not implemented") return App.ActiveDocument.openTransaction( translate("Gespal3D", transaction_name)) Gui.addModule("freecad.workbench_gespal3d.g3d_beam") for command in commands: Gui.doCommand(command) App.ActiveDocument.commitTransaction() App.ActiveDocument.recompute() if self.continueCmd: self.Activated() return else: return
def makeG3DBeam( g3d_profile=None, p1=[0.0, 0.0, 0.0], p2=[1000.0, 0.0, 0.0], anchor=4, inclination=0.0, ): """ Create a G3D Beam (Arch Structure) from a given profile, with sprecified length, color and description. :param g3d_profile: list :param p1: list[float] :param p2: list[float] :param anchor: int :param inclination: float :param description: str :return: object """ print_debug([ "", "makeG3DBeam called with :", "g3d_profile : {}, type : {}".format(g3d_profile, type(g3d_profile)), "p1 : {}, type : {}".format(p1, type(p1)), "p2 : {}, type : {}".format(p2, type(p2)), "anchor : {}, type : {}".format(anchor, type(anchor)), "inclination : {}, type : {}".format(inclination, type(inclination)), "", ]) p1 = App.Vector(p1[0], p1[1], p1[2]) p2 = App.Vector(p2[0], p2[1], p2[2]) if g3d_profile is None: section = g3d_profiles_parser.makeProfile() else: section = g3d_profiles_parser.makeProfile(profile=g3d_profile) if g3d_profile[6] == 'R': height = section.Height width = section.Width elif g3d_profile[6] == 'C': height = width = section.Diameter length = DraftVecUtils.dist(p1, p2) delta_list = [ App.Vector(height / 2, -width / 2, 0), App.Vector(0, -width / 2, 0), App.Vector(-height / 2, -width / 2, 0), App.Vector(height / 2, 0, 0), App.Vector(0, 0, 0), App.Vector(-height / 2, 0, 0), App.Vector(height / 2, width / 2, 0), App.Vector(0, width / 2, 0), App.Vector(-height / 2, width / 2, 0), ] delta = delta_list[anchor] pl = App.Placement() # objet Placement pl.Base = p1 # base est coordonnée p1 zaxis = p2.sub(p1) # zaxis = soustraction de p2 - p1 inclination = inclination * -1 if zaxis.x == 0 and zaxis.y == 0: # orientation verticale up = App.Vector(0, -1, 0) yaxis = up.cross(zaxis) # yaxis = produit vectoriel entre Z et zaxis xaxis = zaxis.cross( yaxis) # xaxis = produit vectoriel entre zaxis et yaxis pl.Rotation = App.Rotation(xaxis, yaxis, zaxis, "ZXY") #inclination = inclination + 180.0 inclination = inclination + 90.0 pl.Rotation = App.Rotation(pl.Rotation.multVec(App.Vector(0, 0, 1)), inclination).multiply(pl.Rotation) else: up = App.Vector(0, 0, 1) # vector up = Z yaxis = up.cross(zaxis) # yaxis = produit vectoriel entre Z et zaxis xaxis = zaxis.cross( yaxis) # xaxis = produit vectoriel entre zaxis et yaxis pl.Rotation = App.Rotation(xaxis, yaxis, zaxis, "ZXY") inclination = inclination + 90.0 pl.Rotation = App.Rotation(pl.Rotation.multVec(App.Vector(0, 0, 1)), inclination).multiply(pl.Rotation) delta = pl.Rotation.multVec(delta) pl.Base = p1.add(delta) section.Placement = pl beam = Arch.makeStructure(section, length=length) beam.Profile = g3d_profile[1] # Set color color = g3d_profile[7].split(",") r = float(color[0]) / 255.0 g = float(color[1]) / 255.0 b = float(color[2]) / 255.0 beam.ViewObject.ShapeColor = (r, g, b) beam.Label = g3d_profile[1] beam.IfcType = u"Transport Element" beam.PredefinedType = u"NOTDEFINED" beam.Tag = u"Gespal" beam.Description = str(g3d_profile[0]) beam.MoveBase = True App.activeDocument().recompute(None, True, True) return beam
def createShadow(self,structure=None): self.clickCount=0 if not self.evalrot[2] in self.beam.orientation: self.beam.length= DraftVecUtils.dist(self.points[0],self.points[1]) #Beam creation if self.structure: self.structure=structure else : #beam cut view if self.evalrot[2] in self.beam.orientation: pass self.structure=Arch.makeStructure(None, self.beam.length,self.beam.width,self.beam.height) self.vecAngle=FreeCAD.Vector(0,0,0) self.vecAngle[0]=self.points[1][0]-self.points[0][0] self.vecAngle[1]=self.points[1][1]-self.points[0][1] self.vecAngle[2]=self.points[1][2]-self.points[0][2] #get rotations between zplan and current plan YESSSS self.wplan=FreeCAD.DraftWorkingPlane self.rotPlan=self.wplan.getRotation().Rotation #Initialize placement # set the origin point self.initialPlacement=FreeCAD.Base.Placement(self.points[0], FreeCAD.Rotation(0,0,0), FreeCAD.Vector(0,0,0)) # Rotate beam on workingplane self.initialPlacement=self.initialPlacement * FreeCAD.Base.Placement(FreeCAD.Vector(0,0,0), self.rotPlan) self.structure.Placement=self.initialPlacement #beam defaultview is from face self.structure.Placement=self.structure.Placement * FreeCAD.Base.Placement(FreeCAD.Vector(0,0,0), FreeCAD.Rotation(0,0,-90)) #beam up view if self.evalrot[1] in self.beam.orientation: self.structure.Placement=self.structure.Placement * FreeCAD.Base.Placement(FreeCAD.Vector(0,0,0), FreeCAD.Rotation(0,0,90)) #beam cut view elif self.evalrot[2] in self.beam.orientation: self.structure.Placement=self.structure.Placement * FreeCAD.Base.Placement(FreeCAD.Vector(0,0,0), FreeCAD.Rotation(90,0,0)) ''' now beam is oriented we have to apply offset gived by Snapper (numpad is too hard to make it working) ''' BeamOffset(self.beam,self.points[0],self.structure) FreeCAD.ActiveDocument.recompute() #set Angle #get normal of current workplane self.normal=FreeCAD.DraftWorkingPlane.getNormal() # get angle in radians between two point with the given normal plan self.localPoints=[] self.localPoints.append(FreeCAD.DraftWorkingPlane.getLocalCoords(self.points[0])) self.localPoints.append(FreeCAD.DraftWorkingPlane.getLocalCoords(self.points[1])) self.vecAngle=FreeCAD.Vector(0,0,0) #relative vector angle self.vecAngle[0]=self.localPoints[1][0]-self.localPoints[0][0] self.vecAngle[1]=self.localPoints[1][1]-self.localPoints[0][1] self.vecAngle[2]=self.localPoints[1][2]-self.localPoints[0][2] #along workingplane normal Console.PrintMessage("##BeamTracker## Workplan normal "+str(self.normal)+"\r\n") self.angle=DraftVecUtils.angle(self.vecAngle,normal=self.normal) Console.PrintMessage("##BeamTracker## Angle before "+str(self.angle)+"°\r\n") ####WARNING #angles 90 and -90 are inverted on Draft on XY plan if self.normal == FreeCAD.Vector(0.0,0.0,1.0): self.normal=FreeCAD.Vector(0,0,-1) self.angle=degrees(self.angle) Draft.rotate(self.structure,self.angle,center=self.points[0],axis=self.normal,copy=False) FreeCAD.ActiveDocument.recompute() #set Attributes self.structure.ViewObject.Transparency=50 self.structure.IfcType="Beam" self.structure.Tag="Wood-Frame" self.structure.Label=self.beam.name # then recompute FreeCAD.ActiveDocument.recompute() Console.PrintMessage("##BeamTracker## Hit ENTER to terminate\r\n")
def action(self, arg): """Handle the 3D scene events. This is installed as an EventCallback in the Inventor view. Parameters ---------- arg: dict Dictionary with strings that indicates the type of event received from the 3D view. """ import DraftGeomUtils if arg["Type"] == "SoKeyboardEvent": if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": # mouse movement detection self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) # this is to make sure radius is what you see on screen if self.center and DraftVecUtils.dist(self.point, self.center) > 0: viewdelta = DraftVecUtils.project(self.point.sub(self.center), App.DraftWorkingPlane.axis) if not DraftVecUtils.isNull(viewdelta): self.point = self.point.add(viewdelta.negative()) if self.step == 0: # choose center if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): if not self.altdown: self.altdown = True self.ui.switchUi(True) else: if self.altdown: self.altdown = False self.ui.switchUi(False) else: # choose radius if len(self.tangents) == 2: cir = DraftGeomUtils.circleFrom2tan1pt( self.tangents[0], self.tangents[1], self.point) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: cir = DraftGeomUtils.circleFrom1tan2pt( self.tangents[0], self.tanpoints[0], self.point) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): if not self.altdown: self.altdown = True snapped = self.view.getObjectInfo( (arg["Position"][0], arg["Position"][1])) if snapped: ob = self.doc.getObject(snapped['Object']) num = int(snapped['Component'].lstrip('Edge')) - 1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: cir = DraftGeomUtils.circleFrom3tan( self.tangents[0], self.tangents[1], ed) cl = DraftGeomUtils.findClosestCircle( self.point, cir) self.center = cl.Center self.rad = cl.Radius self.arctrack.setCenter(self.center) else: self.rad = self.center.add( DraftGeomUtils.findDistance( self.center, ed).sub(self.center)).Length else: self.rad = DraftVecUtils.dist(self.point, self.center) else: if self.altdown: self.altdown = False self.rad = DraftVecUtils.dist(self.point, self.center) self.ui.setRadiusValue(self.rad, 'Length') self.arctrack.setRadius(self.rad) gui_tool_utils.redraw3DView() elif (arg["Type"] == "SoMouseButtonEvent" and arg["State"] == "DOWN" and arg["Button"] == "BUTTON1"): # mouse click if self.point: if self.step == 0: # choose center if (not self.node) and (not self.support): gui_tool_utils.getSupport(arg) (self.point, ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): snapped = self.view.getObjectInfo( (arg["Position"][0], arg["Position"][1])) if snapped: ob = self.doc.getObject(snapped['Object']) num = int(snapped['Component'].lstrip('Edge')) - 1 ed = ob.Shape.Edges[num] self.tangents.append(ed) if len(self.tangents) == 2: self.arctrack.on() self.ui.radiusUi() self.step = 1 _msg(translate("draft", "Pick radius")) else: if len(self.tangents) == 1: self.tanpoints.append(self.point) else: self.center = self.point self.node = [self.point] self.arctrack.setCenter(self.center) self.arctrack.on() self.ui.radiusUi() self.step = 1 _msg(translate("draft", "Pick radius")) if self.planetrack: self.planetrack.set(self.point) elif self.step == 1: # choose radius self.drawPolygon()
def action(self, arg): """Handle the 3D scene events. This is installed as an EventCallback in the Inventor view. Parameters ---------- arg: dict Dictionary with strings that indicates the type of event received from the 3D view. """ import DraftGeomUtils plane = App.DraftWorkingPlane if arg["Type"] == "SoKeyboardEvent": if arg["Key"] == "ESCAPE": self.finish() elif arg["Type"] == "SoLocation2Event": # mouse movement detection self.point, ctrlPoint, info = gui_tool_utils.getPoint(self, arg) # this is to make sure radius is what you see on screen if self.center and DraftVecUtils.dist(self.point, self.center) > 0: viewdelta = DraftVecUtils.project(self.point.sub(self.center), plane.axis) if not DraftVecUtils.isNull(viewdelta): self.point = self.point.add(viewdelta.negative()) if self.step == 0: # choose center if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): if not self.altdown: self.altdown = True self.ui.switchUi(True) else: if self.altdown: self.altdown = False self.ui.switchUi(False) elif self.step == 1: # choose radius if len(self.tangents) == 2: cir = DraftGeomUtils.circleFrom2tan1pt(self.tangents[0], self.tangents[1], self.point) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) elif self.tangents and self.tanpoints: cir = DraftGeomUtils.circleFrom1tan2pt(self.tangents[0], self.tanpoints[0], self.point) _c = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = _c.Center self.arctrack.setCenter(self.center) if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): if not self.altdown: self.altdown = True if info: ob = self.doc.getObject(info['Object']) num = int(info['Component'].lstrip('Edge')) - 1 ed = ob.Shape.Edges[num] if len(self.tangents) == 2: cir = DraftGeomUtils.circleFrom3tan(self.tangents[0], self.tangents[1], ed) cl = DraftGeomUtils.findClosestCircle(self.point, cir) self.center = cl.Center self.rad = cl.Radius self.arctrack.setCenter(self.center) else: self.rad = self.center.add(DraftGeomUtils.findDistance(self.center, ed).sub(self.center)).Length else: self.rad = DraftVecUtils.dist(self.point, self.center) else: if self.altdown: self.altdown = False self.rad = DraftVecUtils.dist(self.point, self.center) self.ui.setRadiusValue(self.rad, "Length") self.arctrack.setRadius(self.rad) self.linetrack.p1(self.center) self.linetrack.p2(self.point) self.linetrack.on() elif (self.step == 2): # choose first angle currentrad = DraftVecUtils.dist(self.point, self.center) if currentrad != 0: angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis) else: angle = 0 self.linetrack.p2(DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center)) self.ui.setRadiusValue(math.degrees(angle), unit="Angle") self.firstangle = angle else: # choose second angle currentrad = DraftVecUtils.dist(self.point, self.center) if currentrad != 0: angle = DraftVecUtils.angle(plane.u, self.point.sub(self.center), plane.axis) else: angle = 0 self.linetrack.p2(DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad).add(self.center)) self.updateAngle(angle) self.ui.setRadiusValue(math.degrees(self.angle), unit="Angle") self.arctrack.setApertureAngle(self.angle) gui_tool_utils.redraw3DView() elif arg["Type"] == "SoMouseButtonEvent": # mouse click if arg["State"] == "DOWN" and arg["Button"] == "BUTTON1": if self.point: if self.step == 0: # choose center if not self.support: gui_tool_utils.getSupport(arg) (self.point, ctrlPoint, info) = gui_tool_utils.getPoint(self, arg) if gui_tool_utils.hasMod(arg, gui_tool_utils.MODALT): snapped = self.view.getObjectInfo((arg["Position"][0], arg["Position"][1])) if snapped: ob = self.doc.getObject(snapped['Object']) num = int(snapped['Component'].lstrip('Edge')) - 1 ed = ob.Shape.Edges[num] self.tangents.append(ed) if len(self.tangents) == 2: self.arctrack.on() self.ui.radiusUi() self.step = 1 self.ui.setNextFocus() self.linetrack.on() _msg(translate("draft", "Pick radius")) else: if len(self.tangents) == 1: self.tanpoints.append(self.point) else: self.center = self.point self.node = [self.point] self.arctrack.setCenter(self.center) self.linetrack.p1(self.center) self.linetrack.p2(self.view.getPoint(arg["Position"][0], arg["Position"][1])) self.arctrack.on() self.ui.radiusUi() self.step = 1 self.ui.setNextFocus() self.linetrack.on() _msg(translate("draft", "Pick radius")) if self.planetrack: self.planetrack.set(self.point) elif self.step == 1: # choose radius if self.closedCircle: self.drawArc() else: self.ui.labelRadius.setText(translate("draft", "Start angle")) self.ui.radiusValue.setToolTip(translate("draft", "Start angle")) self.ui.radiusValue.setText(U.Quantity(0, U.Angle).UserString) self.linetrack.p1(self.center) self.linetrack.on() self.step = 2 _msg(translate("draft", "Pick start angle")) elif self.step == 2: # choose first angle self.ui.labelRadius.setText(translate("draft", "Aperture angle")) self.ui.radiusValue.setToolTip(translate("draft", "Aperture angle")) self.step = 3 # scale center->point vector for proper display # u = DraftVecUtils.scaleTo(self.point.sub(self.center), self.rad) obsolete? self.arctrack.setStartAngle(self.firstangle) _msg(translate("draft", "Pick aperture")) else: # choose second angle self.step = 4 self.drawArc()