Difference between revisions of "Line drawing function"

From FreeCAD Documentation
Jump to navigation Jump to search
m
Line 1: Line 1:
'''Note - This page is in construction and the script below won't work at the moment.'''
+
This page shows how advanced functionality can easily be built in python. In this exercise, we will be building a new tool that draws a line. This tool can then be linked to a freecad command, and that command can be called by any element of the interface, like a menu item or a toolbar button.
 
 
This page shows how advanced functionality can easily be built in python. In this exercise, we will be building a new function that draws a line. This fuction can then be linked to a freecad command, and that command can be called by any element of the interface, like a menu item or a toolbar button.
 
  
 
===The main script===
 
===The main script===
  
First we will make a script containing all our functionality. We will make a '''getpoint''' function, then a '''line''' function that will, when executed, call two times the '''getpoint''' function, then draw the line. Here is our script:
+
First we will write a script containing all our functionality. Then, we will save this in a file, and import it in FreeCAD, so all classes and functions we write will be availible to FreeCAD. So, launch your favorite text editor, and type the following lines:
  
 
<code python>
 
<code python>
  
 
import FreeCADGui, Part
 
import FreeCADGui, Part
 +
  class line:
 +
    "this class will creates a line after the user clicked 2 points on the screen"
 +
    def __init__(self):
 +
      self.view = FreeCADGui.ActiveDocument.ActiveView
 +
      self.stack = []
 +
      self.callback = self.view.addEventCallback("SoMouseButtonEvent",self.getpoint)
 +
      print "click the two points of the line"
 +
    def getpoint(self,info):
 +
      if info["State"] == "DOWN":
 +
        pos = info["Position"]
 +
        point = self.view.getPoint(pos[0],pos[1])
 +
        self.stack.append(point)
 +
        if len(self.stack) == 2:
 +
          self.drawline()
 +
    def drawline(self):
 +
      l = Part.Line(self.stack[0],self.stack[1])
 +
      shape = l.toShape()
 +
      Part.show(shape)
 +
      self.view.removeEventCallback("SoMouseButtonEvent",self.callback)
 +
 +
</code>
  
def getpoint():
+
===Detailed explanation===
  "this function returns (x,y,z) coordinates from a mouse click"
 
  view = FreeCADGui.ActiveDocument.ActiveView
 
  point = None
 
  
  def getposition(info):
+
<code python>import Part, FreeCADGui</code>
    down = (info["State"] == "DOWN")
 
    pos = info["Position"]
 
    if (down):
 
      point =  view.getPoint(pos[0],pos[1])
 
  
  callback = view.addEventCallback("SoMouseButtonEvent",getposition)
+
In python, when you want to use functions from another module, you need to import it. In our case, we will need functions from the Part module, for creating the line, and from the Gui module (FreeCADGui), for accessing the 3D view.
  while not (point):
 
    pass
 
 
 
  view.removeEventCallback(callback)
 
  return (point.x,point.y,point.z)
 
  
 +
<code python>class line:</code>
  
def line():
+
Here we define our main class. Why do we use a class and not a function? The reason is that we need our tool to stay "alive" while we are waiting for the user to click on the screen. A function ends when its task has been done, but an object (a class defines an object) stays alive until it is destroyed.
  "this function creates a line"
 
  x1,y1,z1 = getpoint()
 
  x2,y2,z2 = getpoint()
 
  newline = Part.makeLine((x1,y1,z1),(x2,y2,z2))
 
  Part.show(newline)
 
  
</code>
+
<code python>"this class will creates a line after the user clicked 2 points on the screen"</code>
  
===Explanation===
+
In python, every class or function can have a description string. This is particularly useful in FreeCAD, because when you'll call that class in the interpreter, the description string will be displayed as a tooltip.
  
import Part, FreeCADGui
+
<code python>def __init__(self):</code>
  
In python, when you want to use functions from another module, you need to import it before. In our case, we will need functions from the Part module, for creating the line, and frm the Gui module (FreeCADGui), for manipulating the 3D view.
+
Python classes can always contain an __Init__ function, which is executed when the class is called to create an object. So, we will put here everything we want to happen when our line tool begins.
  
def getpoint():
+
<code python>self.view = FreeCADGui.ActiveDocument.ActiveView</code>
  
Here we define our first function. It is a good habit, when creating functions and classes, to start them imediately with a string describing what the function does. When you will use this function from the freecad python interpreter, this string will appear as a tooltip.
+
In a class, you usually want to append ''self.'' before a variable name, so it will be easily accessible to all functions in that class. Here, we will use self.view to access and manipulate the active 3D view.

Revision as of 21:42, 31 October 2008

This page shows how advanced functionality can easily be built in python. In this exercise, we will be building a new tool that draws a line. This tool can then be linked to a freecad command, and that command can be called by any element of the interface, like a menu item or a toolbar button.

The main script

First we will write a script containing all our functionality. Then, we will save this in a file, and import it in FreeCAD, so all classes and functions we write will be availible to FreeCAD. So, launch your favorite text editor, and type the following lines:

import FreeCADGui, Part

 class line:
   "this class will creates a line after the user clicked 2 points on the screen"
   def __init__(self):
     self.view = FreeCADGui.ActiveDocument.ActiveView
     self.stack = []
     self.callback = self.view.addEventCallback("SoMouseButtonEvent",self.getpoint)
     print "click the two points of the line"
   def getpoint(self,info):
     if info["State"] == "DOWN":
       pos = info["Position"]
       point = self.view.getPoint(pos[0],pos[1])
       self.stack.append(point)
       if len(self.stack) == 2:
         self.drawline()
   def drawline(self):
     l = Part.Line(self.stack[0],self.stack[1])
     shape = l.toShape()
     Part.show(shape)
     self.view.removeEventCallback("SoMouseButtonEvent",self.callback)

Detailed explanation

import Part, FreeCADGui

In python, when you want to use functions from another module, you need to import it. In our case, we will need functions from the Part module, for creating the line, and from the Gui module (FreeCADGui), for accessing the 3D view.

class line:

Here we define our main class. Why do we use a class and not a function? The reason is that we need our tool to stay "alive" while we are waiting for the user to click on the screen. A function ends when its task has been done, but an object (a class defines an object) stays alive until it is destroyed.

"this class will creates a line after the user clicked 2 points on the screen"

In python, every class or function can have a description string. This is particularly useful in FreeCAD, because when you'll call that class in the interpreter, the description string will be displayed as a tooltip.

def __init__(self):

Python classes can always contain an __Init__ function, which is executed when the class is called to create an object. So, we will put here everything we want to happen when our line tool begins.

self.view = FreeCADGui.ActiveDocument.ActiveView

In a class, you usually want to append self. before a variable name, so it will be easily accessible to all functions in that class. Here, we will use self.view to access and manipulate the active 3D view.