Civil engineering feature implementation (Transportation Engineering)

Have some feature requests, feedback, cool stuff to share, or want to know where FreeCAD is going? This is the place.
Forum rules
Be nice to others! Read the FreeCAD code of conduct!
User avatar
HakanSeven12
Veteran
Posts: 1481
Joined: Wed Feb 06, 2019 10:30 pm

Re: Civil engineering feature implementation (Transportation Engineering)

Post by HakanSeven12 »

I think git assistant can't handle submodule of the submodule. So it can be good to make support the submodule of the trails, not pivy_trackers.
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: Civil engineering feature implementation (Transportation Engineering)

Post by Joel_graff »

HakanSeven12 wrote: Tue Jun 02, 2020 2:06 pm I think git assistant can't handle submodule of the submodule. So it can be good to make support the submodule of the trails, not pivy_trackers.
I was having the same thoughts - perhaps submodules should only be top-level references, which means they should be at the workbench level only. At very least, it may help eliminate confusion and recursive references.

I'll see what I can do.
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
User avatar
HakanSeven12
Veteran
Posts: 1481
Joined: Wed Feb 06, 2019 10:30 pm

Re: Civil engineering feature implementation (Transportation Engineering)

Post by HakanSeven12 »

Here my first test for sogeo fpo point group object. What are you thinking about it?

Code: Select all

'''Examples for a feature class and its view provider.'''

import FreeCAD, FreeCADGui
from pivy import coin

class PointGroup:
    def __init__(self, obj):
        '''Add some custom properties to our box feature'''
        obj.addProperty("App::PropertyVectorList", "Points", "Base", "List of group points").Points = ()
        obj.Proxy = self
        self.Points = None
   
    def onChanged(self, fp, prop):
        '''Do something when a property has changed'''
        FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
 
    def execute(self, fp):
        '''Do something when doing a recomputation, this method is mandatory'''
        FreeCAD.Console.PrintMessage("Recompute Python Box feature\n")

class ViewProviderPointGroup:
    def __init__(self, obj):
        '''Set this object to the proxy object of the actual view provider'''
        obj.addProperty("App::PropertyColor","Color","Box","Color of the box").Color=(1.0,0.0,0.0)
        obj.Proxy = self
 
    def attach(self, obj):
        '''Setup the scene sub-graph of the view provider, this method is mandatory'''
        sg = FreeCADGui.ActiveDocument.ActiveView.getSceneGraph()
        first_node = sg.getChild(1)
        node_name = first_node.getClassTypeId().getName()
        if node_name == "GeoOrigin":
            geo_system =  first_node.geoSystem.getValues()
            geo_coord =  first_node.geoCoords.getValue().getValue()
        self.coord = coin.SoGeoCoordinate()
        self.coord.geoSystem.setValues(geo_system)
        self.coord.point.values = obj.Object.Points
        data = coin.SoPointSet()

        self.sep = coin.SoGeoSeparator()
        self.sep.geoSystem.setValues(geo_system)
        self.sep.geoCoords.setValue(geo_coord[0], geo_coord[1], geo_coord[2])

        self.shaded = self.sep
        self.wireframe = self.sep
        self.color = coin.SoBaseColor()
       
        self.shaded.addChild(self.color)
        self.shaded.addChild(self.coord)
        self.shaded.addChild(data)
        obj.addDisplayMode(self.shaded,"Shaded")
        style=coin.SoDrawStyle()
        style.style = coin.SoDrawStyle.LINES
        self.wireframe.addChild(style)
        self.wireframe.addChild(self.color)
        self.wireframe.addChild(self.coord)
        self.wireframe.addChild(data)
        obj.addDisplayMode(self.wireframe,"Wireframe")
        self.onChanged(obj,"Color")
 
    def updateData(self, fp, prop):
        '''If a property of the handled feature has changed we have the chance to handle this here'''
        # fp is the handled feature, prop is the name of the property that has changed
        """
        l = fp.getPropertyByName("Length")
        w = fp.getPropertyByName("Width")
        h = fp.getPropertyByName("Height")
        self.scale.scaleFactor.setValue(float(l),float(w),float(h))
        """
        pass
 
    def getDisplayModes(self,obj):
        '''Return a list of display modes.'''
        modes=[]
        modes.append("Shaded")
        modes.append("Wireframe")
        return modes
 
    def getDefaultDisplayMode(self):
        '''Return the name of the default display mode. It must be defined in getDisplayModes.'''
        return "Shaded"
 
    def setDisplayMode(self,mode):
        '''Map the display mode defined in attach with those defined in getDisplayModes.\
                Since they have the same names nothing needs to be done. This method is optional'''
        return mode
 
    def onChanged(self, vp, prop):
        '''Here we can do something when a single property got changed'''
        FreeCAD.Console.PrintMessage("Change property: " + str(prop) + "\n")
        if prop == "Color":
            c = vp.getPropertyByName("Color")
            self.color.rgb.setValue(c[0],c[1],c[2])
 
    def getIcon(self):
        '''Return the icon in XPM format which will appear in the tree view. This method is\
                optional and if not defined a default icon is shown.'''
        return """
            /* XPM */
            static const char * ViewProviderBox_xpm[] = {
            "16 16 6 1",
            "   c None",
            ".  c #141010",
            "+  c #615BD2",
            "@  c #C39D55",
            "#  c #000000",
            "$  c #57C355",
            "        ........",
            "   ......++..+..",
            "   .@@@@.++..++.",
            "   .@@@@.++..++.",
            "   .@@  .++++++.",
            "  ..@@  .++..++.",
            "###@@@@ .++..++.",
            "##$.@@$#.++++++.",
            "#$#$.$$$........",
            "#$$#######      ",
            "#$$#$$$$$#      ",
            "#$$#$$$$$#      ",
            "#$$#$$$$$#      ",
            " #$#$$$$$#      ",
            "  ##$$$$$#      ",
            "   #######      "};
            """
 
    def __getstate__(self):
        '''When saving the document this object gets stored using Python's json module.\
                Since we have some un-serializable parts here -- the Coin stuff -- we must define this method\
                to return a tuple of all serializable objects or None.'''
        return None
 
    def __setstate__(self,state):
        '''When restoring the serialized object from document we have the chance to set some internals here.\
                Since no data were serialized nothing needs to be done here.'''
        return None


def create():
    obj=FreeCAD.ActiveDocument.addObject("App::FeaturePython","Box")
    PointGroup(obj)
    obj.Points = ((4275011518.128912, 507510589.4751387, 0.0),
(4275011717.0043764, 507511569.4996429, 0.0),
(4275011913.4291606, 507512550.0182727, 0.0),
(4275012107.4020367, 507513531.0248998, 0.0),
(4275012298.921793, 507514512.5133929, 0.0))
    ViewProviderPointGroup(obj.ViewObject)

create()
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: Civil engineering feature implementation (Transportation Engineering)

Post by Joel_graff »

If it works, go for it. :) Off hand, I don't see much in the code, except tha tyou might want to add code to destroy the node graph when the object is deleted...

I'm still working through the submodule issue. I've got most of it sorted out. Was going to try a FeaturePython implementation that uses pivy_trackers for SoGeo nodes as well - I'm gong to have to get rid of my use of lines in horizontal alignments.

Whatever you come up with will certainly be more lightweight, though.
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
User avatar
HakanSeven12
Veteran
Posts: 1481
Joined: Wed Feb 06, 2019 10:30 pm

Re: Civil engineering feature implementation (Transportation Engineering)

Post by HakanSeven12 »

it works :) I didn't have any problem with object deleting. I don't think I need code for deleting.
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: Civil engineering feature implementation (Transportation Engineering)

Post by Joel_graff »

One thing that needs to happen is creating a default separator / GeoOrigin when the workbench is activated, then removing it when it's deleted.

I think it's reasonable to assume most all work will require it, and there can't be more than one in a scenegraph, so I think it should be added as a singleton at the workbench initialization...
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
User avatar
HakanSeven12
Veteran
Posts: 1481
Joined: Wed Feb 06, 2019 10:30 pm

Re: Civil engineering feature implementation (Transportation Engineering)

Post by HakanSeven12 »

What about creating a feature python object for it? We can save it to document.
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: Civil engineering feature implementation (Transportation Engineering)

Post by Joel_graff »

HakanSeven12 wrote: Thu Jun 04, 2020 4:06 pm What about creating a feature python object for it? We can save it to document.
I really don't see any value to wrapping the top level node structure in a FeaturePython object...

I was thinking that when the workbench is initialized, we create an SoSeparator node with an SoGeoOrigin node under it, and make it a global singleton that's available everywhere. Then, you and I need only add SoGeo* nodes or other nodes as children of that SoSeparator if they rely on geo-referencing.

We could also create a singleton SoSeparator that is *not* geo-referenced (before the SoSeparator with the SoGeoOrigin), should we want to add nodes that are not affected by geo-referencing.

In any case, when the workbench/document is closed (or some other event requires destroying the data), we only need to remove the top separator node(s) to ensure all scenegraph changes are destroyed.
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
User avatar
HakanSeven12
Veteran
Posts: 1481
Joined: Wed Feb 06, 2019 10:30 pm

Re: Civil engineering feature implementation (Transportation Engineering)

Post by HakanSeven12 »

I think that can cause problems when reopening saved document which contains SoGeo nodes. Because there won't be SoGeoOrigin but there will be other SoGeo nodes.
User avatar
Joel_graff
Veteran
Posts: 1949
Joined: Fri Apr 28, 2017 4:23 pm
Contact:

Re: Civil engineering feature implementation (Transportation Engineering)

Post by Joel_graff »

HakanSeven12 wrote: Thu Jun 04, 2020 4:36 pm I think that can cause problems when reopening saved document which contains SoGeo nodes. Because there won't be SoGeoOrigin but there will be other SoGeo nodes.
So long as the workbench is activated, it should be fine. But if it isn't, then it would be an issue...
FreeCAD Trails workbench for transportation engineering: https://www.github.com/joelgraff/freecad.trails

pivy_trackers 2D coin3D library: https://www.github.com/joelgraff/pivy_trackers
Post Reply