<commit_before>#***************************************************************************
#*                                                                         *
#*   Copyright (c) 2015 - <NAME> (DeepSOIC)                          *
#*                                               <<EMAIL>>      *  
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
#*   as published by the Free Software Foundation; either version 2 of     *
#*   the License, or (at your option) any later version.                   *
#*   for detail see the LICENCE text file.                                 *
#*                                                                         *
#*   This program is distributed in the hope that it will be useful,       *
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
#*   GNU Library General Public License for more details.                  *
#*                                                                         *
#*   You should have received a copy of the GNU Library General Public     *
#*   License along with this program; if not, write to the Free Software   *
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
#*   USA                                                                   *
#*                                                                         *
#***************************************************************************

__title__="Base feature module for lattice object of lattice workbench for FreeCAD"
__author__ = "DeepSOIC"
__url__ = ""

import FreeCAD as App
import Part

from latticeCommon import *
import latticeCompoundExplorer as LCE
import latticeMarkers
import latticeExecuter

def getDefLatticeFaceColor():
    return (1.0, 0.7019608020782471, 0.0, 0.0) #orange
def getDefShapeColor():
    clr = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View").GetUnsigned("DefaultShapeColor")
    #convert color in int to color in tuple of 4 floats.
    #This is probably implemented already somewhere, but I couldn't find, so I rolled my own --DeepSOIC
    # clr in hex looks like this: 0xRRGGBBOO (r,g,b,o = red, green, blue, opacity)
    o = clr & 0x000000FFL
    b = (clr >> 8) & 0x000000FFL
    g = (clr >> 16) & 0x000000FFL
    r = (clr >> 24) & 0x000000FFL
    return (r/255.0, g/255.0, b/255.0, (255-o)/255.0)
    

def makeLatticeFeature(name, AppClass, ViewClass):
    '''makeLatticeFeature(name, AppClass, ViewClass = None): makes a document object for a LatticeFeature-derived object.'''
    obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
    AppClass(obj)
    if ViewClass:
        vp = ViewClass(obj.ViewObject)
    else:
        vp = ViewProviderLatticeFeature(obj.ViewObject)
        
    return obj
    
    
def isObjectLattice(documentObject):
    '''isObjectLattice(documentObject): When operating on the object, it is to be treated as a lattice object. If False, treat as a regular shape.'''
    ret = False
    if hasattr(documentObject,"isLattice"):
        if 'On' in documentObject.isLattice:
            ret = True
    return ret
    
def getMarkerSizeEstimate(ListOfPlacements):
    '''getMarkerSizeEstimate(ListOfPlacements): computes the default marker size for the array of placements'''
    if len(ListOfPlacements) == 0:
        return 1.0
    pathLength = 0
    for i in range(1, len(ListOfPlacements)):
        pathLength += (ListOfPlacements[i].Base - ListOfPlacements[i-1].Base).Length
    sz = pathLength/len(ListOfPlacements)/2.0
    #FIXME: make hierarchy-aware
    if sz < DistConfusion*10:
        sz = 1.0
    return sz

    


class LatticeFeature():
    "Base object for lattice objects (arrays of placements)"
    
    def __init__(self,obj):
        # please, don't override. Override derivedInit instead.
        self.Type = "latticeFeature"

        prop = "NumElements"
        obj.addProperty("App::PropertyInteger",prop,"Lattice","Info: number of placements in the array")
        obj.setEditorMode(prop, 1) # set read-only
        
        prop = "SingleByDesign"
        obj.addProperty("App::PropertyBool",prop,"Lattice","Makes the element be populated into object's Placement property")
        obj.setEditorMode(prop, 2) # set hidden

        obj.addProperty("App::PropertyLength","MarkerSize","Lattice","Size of placement markers (set to zero for automatic).")
        
        obj.addProperty("App::PropertyEnumeration","MarkerShape","Lattice","Choose the preferred shape of placement markers.")
        obj.MarkerShape = ["tetra-orimarker","paperplane-orimarker"]
        obj.MarkerShape = "paperplane-orimarker" #TODO: setting for choosing the default

        obj.addProperty("App::PropertyEnumeration","isLattice","Lattice","Sets whether this object should be treated as a lattice by further operations")
        obj.isLattice = ['Auto-Off','Auto-On','Force-Off','Force-On']
        # Auto-On an Auto-Off can be modified when recomputing. Force values are going to stay.
        
        self.derivedInit(obj)
        
        obj.Proxy = self

        
    def derivedInit(self, obj):
        '''for overriding by derived classes'''
        pass
        
    def execute(self,obj):
        # please, don't override. Override derivedExecute instead.

        plms = self.derivedExecute(obj)

        if plms is not None:
            obj.NumElements = len(plms)
            shapes = []
            markerSize = obj.MarkerSize
            if markerSize < DistConfusion:
                markerSize = getMarkerSizeEstimate(plms)
            marker = latticeMarkers.getPlacementMarker(scale= markerSize, markerID= obj.MarkerShape)
            #FIXME: make hierarchy-aware
            if obj.SingleByDesign:
                if len(plms) != 1:
                    latticeExecuter.warning(obj,"Multiple placements are being fed, but object is single by design. Only fisrt placement will be used...")
                obj.Shape = marker.copy()
                obj.Placement = plms[0]
            else:
                for plm in plms:
                    sh = marker.copy()
                    sh.Placement = plm
                    shapes.append(sh)
                    
                if len(shapes) == 0:
                    obj.Shape = markers.getNullShapeShape(markerSize)
                    raise ValueError('Lattice object is null') #Feeding empty compounds to FreeCAD seems to cause rendering issues, otherwise it would have been a good idea to output nothing.<commit_msg>Fix empty set marker for lattice arrays<commit_after>#***************************************************************************
#*                                                                         *
#*   Copyright (c) 2015 - <NAME> (DeepSOIC)                          *
#*                                               <<EMAIL>>      *  
#*                                                                         *
#*   This program is free software; you can redistribute it and/or modify  *
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
#*   as published by the Free Software Foundation; either version 2 of     *
#*   the License, or (at your option) any later version.                   *
#*   for detail see the LICENCE text file.                                 *
#*                                                                         *
#*   This program is distributed in the hope that it will be useful,       *
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
#*   GNU Library General Public License for more details.                  *
#*                                                                         *
#*   You should have received a copy of the GNU Library General Public     *
#*   License along with this program; if not, write to the Free Software   *
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
#*   USA                                                                   *
#*                                                                         *
#***************************************************************************

__title__="Base feature module for lattice object of lattice workbench for FreeCAD"
__author__ = "DeepSOIC"
__url__ = ""

import FreeCAD as App
import Part

from latticeCommon import *
import latticeCompoundExplorer as LCE
import latticeMarkers
import latticeExecuter

def getDefLatticeFaceColor():
    return (1.0, 0.7019608020782471, 0.0, 0.0) #orange
def getDefShapeColor():
    clr = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/View").GetUnsigned("DefaultShapeColor")
    #convert color in int to color in tuple of 4 floats.
    #This is probably implemented already somewhere, but I couldn't find, so I rolled my own --DeepSOIC
    # clr in hex looks like this: 0xRRGGBBOO (r,g,b,o = red, green, blue, opacity)
    o = clr & 0x000000FFL
    b = (clr >> 8) & 0x000000FFL
    g = (clr >> 16) & 0x000000FFL
    r = (clr >> 24) & 0x000000FFL
    return (r/255.0, g/255.0, b/255.0, (255-o)/255.0)
    

def makeLatticeFeature(name, AppClass, ViewClass):
    '''makeLatticeFeature(name, AppClass, ViewClass = None): makes a document object for a LatticeFeature-derived object.'''
    obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython",name)
    AppClass(obj)
    if ViewClass:
        vp = ViewClass(obj.ViewObject)
    else:
        vp = ViewProviderLatticeFeature(obj.ViewObject)
        
    return obj
    
    
def isObjectLattice(documentObject):
    '''isObjectLattice(documentObject): When operating on the object, it is to be treated as a lattice object. If False, treat as a regular shape.'''
    ret = False
    if hasattr(documentObject,"isLattice"):
        if 'On' in documentObject.isLattice:
            ret = True
    return ret
    
def getMarkerSizeEstimate(ListOfPlacements):
    '''getMarkerSizeEstimate(ListOfPlacements): computes the default marker size for the array of placements'''
    if len(ListOfPlacements) == 0:
        return 1.0
    pathLength = 0
    for i in range(1, len(ListOfPlacements)):
        pathLength += (ListOfPlacements[i].Base - ListOfPlacements[i-1].Base).Length
    sz = pathLength/len(ListOfPlacements)/2.0
    #FIXME: make hierarchy-aware
    if sz < DistConfusion*10:
        sz = 1.0
    return sz

    


class LatticeFeature():
    "Base object for lattice objects (arrays of placements)"
    
    def __init__(self,obj):
        # please, don't override. Override derivedInit instead.
        self.Type = "latticeFeature"

        prop = "NumElements"
        obj.addProperty("App::PropertyInteger",prop,"Lattice","Info: number of placements in the array")
        obj.setEditorMode(prop, 1) # set read-only
        
        prop = "SingleByDesign"
        obj.addProperty("App::PropertyBool",prop,"Lattice","Makes the element be populated into object's Placement property")
        obj.setEditorMode(prop, 2) # set hidden

        obj.addProperty("App::PropertyLength","MarkerSize","Lattice","Size of placement markers (set to zero for automatic).")
        
        obj.addProperty("App::PropertyEnumeration","MarkerShape","Lattice","Choose the preferred shape of placement markers.")
        obj.MarkerShape = ["tetra-orimarker","paperplane-orimarker"]
        obj.MarkerShape = "paperplane-orimarker" #TODO: setting for choosing the default

        obj.addProperty("App::PropertyEnumeration","isLattice","Lattice","Sets whether this object should be treated as a lattice by further operations")
        obj.isLattice = ['Auto-Off','Auto-On','Force-Off','Force-On']
        # Auto-On an Auto-Off can be modified when recomputing. Force values are going to stay.
        
        self.derivedInit(obj)
        
        obj.Proxy = self

        
    def derivedInit(self, obj):
        '''for overriding by derived classes'''
        pass
        
    def execute(self,obj):
        # please, don't override. Override derivedExecute instead.

        plms = self.derivedExecute(obj)

        if plms is not None:
            obj.NumElements = len(plms)
            shapes = []
            markerSize = obj.MarkerSize
            if markerSize < DistConfusion:
                markerSize = getMarkerSizeEstimate(plms)
            marker = latticeMarkers.getPlacementMarker(scale= markerSize, markerID= obj.MarkerShape)
            #FIXME: make hierarchy-aware
            if obj.SingleByDesign:
                if len(plms) != 1:
                    latticeExecuter.warning(obj,"Multiple placements are being fed, but object is single by design. Only fisrt placement will be used...")
                obj.Shape = marker.copy()
                obj.Placement = plms[0]
            else:
                for plm in plms:
                    sh = marker.copy()
                    sh.Placement = plm
                    shapes.append(sh)
                    
                if len(shapes) == 0:
                    obj.Shape = latticeMarkers.getNullShapeShape(markerSize)
                    raise ValueError('Lattice object is null') #Feeding empty compounds to FreeCAD seems to cause rendering issues, otherwise it would have been a good idea to output nothing.
{'fraction_non_alphanumeric': 0.10883245724439179, 'fraction_numerical': 0.016732064855260236, 'mean_word_length': 2.07489187343501, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 40, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6161720', 'n_tokens_mistral': 3693, 'n_tokens_neox': 3407, 'n_words': 1111}