Texture with grid and output to HPGL file

Post here for help on using FreeCAD's graphical user interface (GUI).
Forum rules
and Helpful information
IMPORTANT: Please click here and read this first, before asking for help

Also, be nice to others! Read the FreeCAD code of conduct!
Leatherman
Posts: 155
Joined: Thu Feb 02, 2017 2:49 pm

Re: Texture with grid and output to HPGL file

Post by Leatherman »

Georg99 wrote: Sat Sep 02, 2017 1:54 pm @Leatherman: I still have problems... I start Freecad and create with WB Part a sphere. Then I copy your code Macro - paste - save .. then I receive this message:
<unknown exception traceback><type 'exceptions.SyntaxError'>: ('invalid syntax', ('C:/Users/baumanng/AppData/Roaming/FreeCAD/IsoCurve.FCMacro', 2, 7, 'Skip to content\n'))

that is the py console:
Python 2.7.8 (default, Nov 17 2014, 20:37:05) [MSC v.1800 64 bit (AMD64)] on win32
Type 'help', 'copyright', 'credits' or 'license' for more information.
>>> App.newDocument("Unbenannt")
>>> App.setActiveDocument("Unbenannt")
>>> App.ActiveDocument=App.getDocument("Unbenannt")
>>> Gui.ActiveDocument=Gui.getDocument("Unbenannt")
>>> Gui.activateWorkbench("PartWorkbench")
>>> App.ActiveDocument.addObject("Part::Sphere","Sphere")
>>> App.ActiveDocument.ActiveObject.Label = "Kugel"
>>> App.ActiveDocument.recompute()
>>> Gui.SendMsgToActiveView("ViewFit")
>>> Gui.SendMsgToActiveView("Run")
>>>
The macro name should be IsoCurve.py. try it again pls. You need to put the macro in the appropriate WB as well.
Georg99
Posts: 50
Joined: Thu Nov 06, 2014 10:08 pm
Location: Germany

Re: Texture with grid and output to HPGL file

Post by Georg99 »

@leatherman: sorry mistake from me ... I copied too much lines ...
now I got an error with sense:
File "C:/Users/baumanng/AppData/Roaming/FreeCAD/IsoCurve.FCMacro", line 14, in <module>
import os, dummy
<type 'exceptions.ImportError'>: No module named dummy
Leatherman
Posts: 155
Joined: Thu Feb 02, 2017 2:49 pm

Re: Texture with grid and output to HPGL file

Post by Leatherman »

Georg99 wrote: Sat Sep 02, 2017 2:10 pm @leatherman: sorry mistake from me ... I copied too much lines ...
now I got an error with sense:
File "C:/Users/baumanng/AppData/Roaming/FreeCAD/IsoCurve.FCMacro", line 14, in <module>
import os, dummy
<type 'exceptions.ImportError'>: No module named dummy
We don't want IsoCurve.FCMacro. Once you save the file you need to type the full macro name incl. ".py"
Georg99
Posts: 50
Joined: Thu Nov 06, 2014 10:08 pm
Location: Germany

Re: Texture with grid and output to HPGL file

Post by Georg99 »

Now I added the IsoCurve.py to the directory of also some other py-files.C:/Users/baumanng/AppData/Roaming/FreeCAD
I checked the file with an external editor - content is ok.
the same error comes up:
Traceback (most recent call last):
File "C:/Users/baumanng/AppData/Roaming/FreeCAD/IsoCurve.py", line 14, in <module>
import os, dummy
<type 'exceptions.ImportError'>: No module named dummy

You wrote "You need to put the macro in the appropriate WB as well."
What WB should I use? (I do not see IsoCurve in the list - which is clear because the load was not successful)
User avatar
Chris_G
Veteran
Posts: 2601
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Texture with grid and output to HPGL file

Post by Chris_G »

I'll try to make it as an independent macro.
right now, it needs the whole workbench since it tries to import other files of the workbench, so it cannot be executed as standalone.
Georg99
Posts: 50
Joined: Thu Nov 06, 2014 10:08 pm
Location: Germany

Re: Texture with grid and output to HPGL file

Post by Georg99 »

Chris_G wrote: Sat Sep 02, 2017 2:23 pm I'll try to make it as an independent macro.
right now, it needs the whole workbench since it tries to import other files of the workbench, so it cannot be executed as standalone.
Great!
User avatar
Chris_G
Veteran
Posts: 2601
Joined: Tue Dec 31, 2013 4:10 pm
Location: France
Contact:

Re: Texture with grid and output to HPGL file

Post by Chris_G »

Please try this :
- select a face in the 3D view
- copy / paste this in the python console :

Code: Select all

import FreeCAD as App
if App.GuiUp:
    import FreeCADGui as Gui

import Part
#import isocurves


class isoCurve:
    '''isoCurve of a surface'''
    def __init__(self, face, direc = 'U', param = 0):
        self.face = None
        self.direction = 'U'
        self.parameter = 0
        if not isinstance(face, Part.Face):
            Msg("Error. Not a face")
        else:
            self.bounds = face.ParameterRange
            self.face = face
        if not direc in 'UV':
            Msg("Direction error")
        else:
            self.direction = direc
        if not isinstance(param, (float, int)):
            Msg("Parameter error")
        else:
            self.parameter = param
        
    def toShape(self):
        if self.direction == 'U':
            self.curve = self.face.Surface.uIso(self.parameter)
            prange = self.bounds[2:4]
        elif self.direction == 'V':
            self.curve = self.face.Surface.vIso(self.parameter)
            prange = self.bounds[0:2]
        return(self.curve.toShape(prange[0],prange[1]))

class multiIso:
    '''defines a set of multiple iso curves on a face'''
    def __init__(self, face, numu = 0, numv = 0):
        self.face = None
        self.paramu = []
        self.paramv = []
        self.uiso = []
        self.viso = []
        if not isinstance(face, Part.Face):
            Msg("Error. Not a face")
        else:
            self.bounds = face.ParameterRange
            self.face = face
        if numu:
            self.setNumberU(numu)
        if numv:
            self.setNumberV(numv)

    def computeU(self):
        self.uiso = []
        for u in self.paramu:
            self.uiso.append(isoCurve(self.face,'U',u))

    def computeV(self):
        self.viso = []
        for v in self.paramv:
            self.viso.append(isoCurve(self.face,'V',v))

    #def compute(self):
        #self.computeU()
        #self.computeV()

    def toShape(self):
        c = []
        for u in self.uiso:
            c.append(u.toShape())
        for v in self.viso:
            c.append(v.toShape())
        return(Part.Compound(c))

    def paramList(self, n, fp, lp):
        rang = lp-fp
        l = []
        if n == 1:
            l = [fp + rang / 2.0]
        elif n == 2:
            l = [fp,lp]
        elif n > 2:
            for i in range(n):
                l.append( fp + 1.0* i* rang / (n-1) )
        return(l)

    def setNumberU(self, n):
        fp = self.bounds[0]
        lp = self.bounds[1]
        self.paramu = self.paramList(n, fp, lp)
        self.computeU()

    def setNumberV(self, n):
        fp = self.bounds[2]
        lp = self.bounds[3]
        self.paramv = self.paramList(n, fp, lp)
        self.computeV()

    def setNumbers(self, nu, nv):
        self.setNumberU(nu)
        self.setNumberV(nv)
            


def makeIsoCurveFeature():
    '''makeIsoCurveFeature(): makes a IsoCurve parametric feature object. Returns the new object.'''
    selfobj = App.ActiveDocument.addObject("Part::FeaturePython","IsoCurve")
    IsoCurve(selfobj)
    ViewProviderIsoCurve(selfobj.ViewObject)
    return selfobj

class IsoCurve:
    "The IsoCurve feature object"
    def __init__(self,selfobj):
        selfobj.addProperty("App::PropertyLinkSub","Face","IsoCurve","Input face")
        selfobj.addProperty("App::PropertyFloat","Parameter","IsoCurve","IsoCurve parameter").Parameter=0.
        selfobj.addProperty("App::PropertyInteger","NumberU","IsoCurve","Number of IsoCurve in U direction").NumberU=5
        selfobj.addProperty("App::PropertyInteger","NumberV","IsoCurve","Number of IsoCurve in V direction").NumberV=5
        selfobj.addProperty("App::PropertyEnumeration","Mode","IsoCurve","Number of IsoCurve").Mode=["Single","Multi"]
        selfobj.addProperty("App::PropertyEnumeration","Orientation","IsoCurve","Curve Orientation").Orientation=["U","V"]
        selfobj.Mode = "Multi"
        selfobj.setEditorMode("Parameter", 2)
        selfobj.setEditorMode("Orientation", 2)
        selfobj.setEditorMode("NumberU", 0)
        selfobj.setEditorMode("NumberV", 0)
        selfobj.Proxy = self

    def split(self, e, t0, t1):
        p0,p1 = e.ParameterRange
        if (t0 > p0) & (t1 < p1):
            w = e.split([t0,t1])
            return w.Edges[1]
        elif (t0 > p0):
            w = e.split(t0)
            return w.Edges[1]
        elif (t1 < p1):
            w = e.split(t1)
            return w.Edges[0]
        else:
            return e

    def getBounds(self, obj):
        face = self.getFace(obj)
        self.u0, self.u1, self.v0, self.v1 = face.ParameterRange

    def getFace(self, obj):
        try:
            n = eval(obj.Face[1][0].lstrip('Face'))
            face = obj.Face[0].Shape.Faces[n-1]
            #self.u0, self.u1, self.v0, self.v1 = self.face.ParameterRange
            return face
        except:
            return None

    def tangentAt(self, selfobj, p):
        if selfobj.Orientation == 'U':
            if (p >= self.v0) & (p <= self.v1):
                return selfobj.Shape.tangentAt(p)
            else:
                App.Console.PrintError("Parameter out of range (%f, %f)\n"%(self.v0,self.v1))
        if selfobj.Orientation == 'V':
            if (p >= self.u0) & (p <= self.u1):
                return selfobj.Shape.tangentAt(p)
            else:
                App.Console.PrintError("Parameter out of range (%f, %f)\n"%(self.u0,self.u1))

    def normalAt(self, selfobj, p):
        face = self.getFace(selfobj)
        if selfobj.Orientation == 'U':
            if (p >= self.v0) & (p <= self.v1):
                return face.normalAt(selfobj.Parameter, p)
            else:
                App.Console.PrintError("Parameter out of range (%f, %f)\n"%(self.v0,self.v1))
        if selfobj.Orientation == 'V':
            if (p >= self.u0) & (p <= self.u1):
                return face.normalAt(p, selfobj.Parameter)
            else:
                App.Console.PrintError("Parameter out of range (%f, %f)\n"%(self.u0,self.u1))


    def execute(self,selfobj):

        face = self.getFace(selfobj)
        #u0,u1,v0,v1 = face.ParameterRange
        if face:
            if selfobj.Mode == 'Multi':
                w = multiIso(face, selfobj.NumberU, selfobj.NumberV).toShape()
            else:
                if selfobj.Orientation == 'U':
                    ci = multiIso(face, 1, 0)
                    ci.paramu = [selfobj.Parameter]
                    ci.computeU()
                else:
                    ci = multiIso(face, 0, 1)
                    ci.paramv = [selfobj.Parameter]
                    ci.computeV()
                w = ci.toShape()
            selfobj.Shape = w
        else:
            return False

    def onChanged(self, selfobj, prop):
        if prop == 'Face':
            face = self.getFace(selfobj)
            self.getBounds(selfobj)
            if selfobj.Orientation == "U":
                self.p0 = self.u0
                self.p1 = self.u1
            else:
                self.p0 = self.v0
                self.p1 = self.v1
        if prop == 'Mode':
            if selfobj.Mode  == "Single":
                selfobj.setEditorMode("Parameter", 0)
                selfobj.setEditorMode("Orientation", 0)
                selfobj.setEditorMode("NumberU", 2)
                selfobj.setEditorMode("NumberV", 2)
            elif selfobj.Mode  == "Multi":
                selfobj.setEditorMode("Parameter", 2)
                selfobj.setEditorMode("Orientation", 2)
                selfobj.setEditorMode("NumberU", 0)
                selfobj.setEditorMode("NumberV", 0)
            selfobj.Proxy.execute(selfobj)
        if prop == 'Parameter':
            if  selfobj.Parameter  < self.p0:
                selfobj.Parameter  = self.p0
            elif selfobj.Parameter  > self.p1:
                selfobj.Parameter  = self.p1
            selfobj.Proxy.execute(selfobj)
        if prop == 'NumberU':
            if  selfobj.NumberU  < 0:
                selfobj.NumberU  = 0
            elif selfobj.NumberU  > 1000:
                selfobj.NumberU  = 1000
            selfobj.Proxy.execute(selfobj)
        if prop == 'NumberV':
            if  selfobj.NumberV  < 0:
                selfobj.NumberV  = 0
            elif selfobj.NumberV  > 1000:
                selfobj.NumberV  = 1000
            selfobj.Proxy.execute(selfobj)
        if prop == 'Orientation':
            self.getBounds(selfobj)
            if selfobj.Orientation == "U":
                self.p0 = self.u0
                self.p1 = self.u1
            else:
                self.p0 = self.v0
                self.p1 = self.v1
            selfobj.Proxy.execute(selfobj)

class ViewProviderIsoCurve:
    def __init__(self,vobj):
        vobj.Proxy = self
       
    #def getIcon(self):
        #return (path_curvesWB_icons+'/isocurve.svg')

    def attach(self, vobj):
        self.ViewObject = vobj
        self.Object = vobj.Object
  
    def setEdit(self,vobj,mode):
        return False
    
    def unsetEdit(self,vobj,mode):
        return

    def __getstate__(self):
        return None

    def __setstate__(self,state):
        return None


def run():
    f = Gui.Selection.Filter("SELECT Part::Feature SUBELEMENT Face COUNT 1..1000")
    try:
        if not f.match():
            raise Exception("Select at least one face.")
        try:
            App.ActiveDocument.openTransaction("Macro IsoCurve")
            r = f.result()
            for e in r:
                for s in e:
                    for f in s.SubElementNames:
                        #App.ActiveDocument.openTransaction("Macro IsoCurve")
                        selfobj = makeIsoCurveFeature()
                        #so = sel[0].SubObjects[0]
                        #p = sel[0].PickedPoints[0]
                        #poe = so.distToShape(Part.Vertex(p))
                        #par = poe[2][0][2]
                        #selfobj.Face = [sel[0].Object,sel[0].SubElementNames]
                        selfobj.Face = [s.Object,f]
                        #selfobj.Parameter = par[0]
                        selfobj.Proxy.execute(selfobj)
        finally:
            App.ActiveDocument.commitTransaction()
    except Exception as err:
        from PySide import QtGui
        mb = QtGui.QMessageBox()
        mb.setIcon(mb.Icon.Warning)
        mb.setText(err.message)
        mb.setWindowTitle("Macro IsoCurve")
        mb.exec_()


if __name__ == '__main__':
    run()


It works here on FC 0.17, but I didn't test it in stable 0.16 ...
Leatherman
Posts: 155
Joined: Thu Feb 02, 2017 2:49 pm

Re: Texture with grid and output to HPGL file

Post by Leatherman »

Georg99 wrote: Sat Sep 02, 2017 2:22 pm You wrote "You need to put the macro in the appropriate WB as well."
What WB should I use? (I do not see IsoCurve in the list - which is clear because the load was not successful)
In the WB where it belongs to, I guess it's the new WB from ChrisG. Have you tried the new Code? If it works you need to paste it in the same way in the particular WB, otherwise FC can't find it.
User avatar
Willem
Veteran
Posts: 1854
Joined: Fri Aug 12, 2016 3:27 pm
Location: Lisse, The Netherlands

Re: Texture with grid and output to HPGL file

Post by Willem »

Hi, adding a ball with a diameter a bit smaller than the "wireframe look" model my, or better NomandC' s system works also
Schermafdruk van 2017-09-02 17-09-24.png
Schermafdruk van 2017-09-02 17-09-24.png (276.38 KiB) Viewed 1480 times
Georg99
Posts: 50
Joined: Thu Nov 06, 2014 10:08 pm
Location: Germany

Re: Texture with grid and output to HPGL file

Post by Georg99 »

@Chris: it's working. (with one exception the sphere: ACCESS VIOLATION at adress 0x00000 during 'READ' operation)
on a ring or cylinder it creates the isocurves nicely..

Now one item is left: the hidden part of the lines are still visible.
Is there a way to supress them as well?
Post Reply