Merge branch 'shallow_copy'

This commit is contained in:
DeepSOIC 2016-08-21 20:56:14 +03:00
commit 3769ea460a
6 changed files with 130 additions and 12 deletions

View File

@ -6,3 +6,4 @@ import lattice2GeomUtils as GeomUtils
import lattice2InterpolatorUtil as InterpolatorUtil import lattice2InterpolatorUtil as InterpolatorUtil
import lattice2Markers as Markers import lattice2Markers as Markers
import lattice2ValueSeriesGenerator as ValueSeriesGenerator import lattice2ValueSeriesGenerator as ValueSeriesGenerator
import lattice2ShapeCopy as ShapeCopy

View File

@ -32,6 +32,7 @@ from lattice2Common import *
import lattice2CompoundExplorer as LCE import lattice2CompoundExplorer as LCE
import lattice2Markers import lattice2Markers
import lattice2Executer import lattice2Executer
from lattice2ShapeCopy import shallowCopy
def getDefLatticeFaceColor(): def getDefLatticeFaceColor():
@ -111,6 +112,21 @@ class LatticeFeature():
self.derivedInit(obj) self.derivedInit(obj)
obj.Proxy = self obj.Proxy = self
def assureProperty(self, selfobj, proptype, propname, defvalue, group, tooltip):
"""assureProperty(selfobj, proptype, propname, defvalue, group, tooltip): adds
a property if one is missing, and sets its value to default. Does nothing if property
already exists. Returns True if property was created, or False if not."""
if hasattr(selfobj, propname):
#todo: check type match
return False
selfobj.addProperty(proptype, propname, group, tooltip)
if defvalue is not None:
setattr(selfobj, propname, defvalue)
return True
def derivedInit(self, obj): def derivedInit(self, obj):
@ -141,17 +157,17 @@ class LatticeFeature():
obj.Placement = App.Placement() obj.Placement = App.Placement()
if bExposing: if bExposing:
obj.Shape = marker.copy() obj.Shape = shallowCopy(marker)
obj.Placement = plms[0] obj.Placement = plms[0]
else: else:
for plm in plms: for plm in plms:
sh = marker.copy() sh = shallowCopy(marker)
sh.Placement = plm sh.Placement = plm
shapes.append(sh) shapes.append(sh)
if len(shapes) == 0: if len(shapes) == 0:
obj.Shape = lattice2Markers.getNullShapeShape(markerSize) obj.Shape = lattice2Markers.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. raise ValueError('Lattice object is null')
sh = Part.makeCompound(shapes) sh = Part.makeCompound(shapes)
obj.Shape = sh obj.Shape = sh

View File

@ -80,7 +80,7 @@ def deselect(sel):
'''deselect(sel): remove objects in sel from selection''' '''deselect(sel): remove objects in sel from selection'''
for selobj in sel: for selobj in sel:
FreeCADGui.Selection.removeSelection(selobj.Object) FreeCADGui.Selection.removeSelection(selobj.Object)
# OCC's Precision::Confusion; should have taken this from FreeCAD but haven't found; unlikely to ever change. # OCC's Precision::Confusion; should have taken this from FreeCAD but haven't found; unlikely to ever change.
DistConfusion = 1e-7 DistConfusion = 1e-7
ParaConfusion = 1e-8 ParaConfusion = 1e-8

View File

@ -35,6 +35,7 @@ import lattice2BaseFeature
import lattice2CompoundExplorer as LCE import lattice2CompoundExplorer as LCE
import lattice2Executer import lattice2Executer
from lattice2PopulateCopies import DereferenceArray from lattice2PopulateCopies import DereferenceArray
import lattice2ShapeCopy as ShapeCopy
# -------------------------- document object -------------------------------------------------- # -------------------------- document object --------------------------------------------------
@ -62,10 +63,18 @@ class LatticePopulateChildren(lattice2BaseFeature.LatticeFeature):
obj.addProperty("App::PropertyLink","PlacementsTo","Lattice PopulateChildren", "Placement or array of placements, containing target locations.") obj.addProperty("App::PropertyLink","PlacementsTo","Lattice PopulateChildren", "Placement or array of placements, containing target locations.")
obj.addProperty("App::PropertyLink","PlacementsFrom", "Lattice PopulateChildren","Placement or array of placements to be treated as origins for PlacementsTo.") obj.addProperty("App::PropertyLink","PlacementsFrom", "Lattice PopulateChildren","Placement or array of placements to be treated as origins for PlacementsTo.")
self.initNewProperties(obj)
def initNewProperties(self, obj):
# properties that can be missing on objects made with earlier version of Lattice2
if self.assureProperty(obj, "App::PropertyEnumeration","Copying", ShapeCopy.copy_types, "Lattice PopulateChildren", "Sets, what method to use for copying shapes."):
self.Copying = ShapeCopy.copy_types[0]
def derivedExecute(self,obj): def derivedExecute(self,obj):
self.initNewProperties(obj)
outputIsLattice = lattice2BaseFeature.isObjectLattice(obj.Object) outputIsLattice = lattice2BaseFeature.isObjectLattice(obj.Object)
if not lattice2BaseFeature.isObjectLattice(obj.Object): if not lattice2BaseFeature.isObjectLattice(obj.Object):
@ -84,13 +93,13 @@ class LatticePopulateChildren(lattice2BaseFeature.LatticeFeature):
# Precompute referencing # Precompute referencing
placements = DereferenceArray(obj, placements, obj.PlacementsFrom, obj.Referencing) placements = DereferenceArray(obj, placements, obj.PlacementsFrom, obj.Referencing)
# initialize output containers and loop variables # initialize output containers and loop variables
outputShapes = [] #output list of shapes outputShapes = [] #output list of shapes
outputPlms = [] #list of placements outputPlms = [] #list of placements
iChild = 0 iChild = 0
numChildren = len(objectPlms) if outputIsLattice else len(objectShapes) numChildren = len(objectPlms) if outputIsLattice else len(objectShapes)
copy_method_index = ShapeCopy.getCopyTypeIndex(obj.Copying)
# the essence # the essence
for iPlm in range(len(placements)): for iPlm in range(len(placements)):
@ -106,8 +115,8 @@ class LatticePopulateChildren(lattice2BaseFeature.LatticeFeature):
objectPlm = objectPlms[iChild] objectPlm = objectPlms[iChild]
outputPlms.append(plm.multiply(objectPlm)) outputPlms.append(plm.multiply(objectPlm))
else: else:
outputShape = objectShapes[iChild].copy() outputShape = ShapeCopy.copyShape(objectShapes[iChild], copy_method_index, plm)
outputShape.Placement = plm.multiply(outputShape.Placement) # outputShape.Placement = plm.multiply(outputShape.Placement) #now done by shape copy routine
outputShapes.append(outputShape) outputShapes.append(outputShape)
iChild += 1 iChild += 1

View File

@ -34,6 +34,7 @@ from lattice2Common import *
import lattice2BaseFeature import lattice2BaseFeature
import lattice2CompoundExplorer as LCE import lattice2CompoundExplorer as LCE
import lattice2Executer import lattice2Executer
import lattice2ShapeCopy as ShapeCopy
# ---------------------------shared code-------------------------------------- # ---------------------------shared code--------------------------------------
def DereferenceArray(obj,placements, lnkFrom, refmode): def DereferenceArray(obj,placements, lnkFrom, refmode):
@ -100,6 +101,9 @@ class LatticePopulateCopies(lattice2BaseFeature.LatticeFeature):
obj.addProperty("App::PropertyEnumeration", propname, "Lattice PopulateCopies","In case single object copy is made, this property controls, if it's packed into compoud or not.") obj.addProperty("App::PropertyEnumeration", propname, "Lattice PopulateCopies","In case single object copy is made, this property controls, if it's packed into compoud or not.")
setattr(obj,propname,["(autosettle)","always", "only if many"]) setattr(obj,propname,["(autosettle)","always", "only if many"])
setattr(obj,propname,"always") # this is to match the old behavior. This is not the default setting for new features. setattr(obj,propname,"always") # this is to match the old behavior. This is not the default setting for new features.
if self.assureProperty(obj, "App::PropertyEnumeration","Copying", ShapeCopy.copy_types, "Lattice PopulateChildren", "Sets, what method to use for copying shapes."):
self.Copying = ShapeCopy.copy_types[0]
def derivedExecute(self,obj): def derivedExecute(self,obj):
self.assureProperties(obj) self.assureProperties(obj)
@ -119,6 +123,8 @@ class LatticePopulateCopies(lattice2BaseFeature.LatticeFeature):
# initialize output containers and loop variables # initialize output containers and loop variables
outputShapes = [] #output list of shapes outputShapes = [] #output list of shapes
outputPlms = [] #list of placements outputPlms = [] #list of placements
copy_method_index = ShapeCopy.getCopyTypeIndex(obj.Copying)
# the essence # the essence
for plm in placements: for plm in placements:
@ -127,8 +133,8 @@ class LatticePopulateCopies(lattice2BaseFeature.LatticeFeature):
for objectPlm in objectPlms: for objectPlm in objectPlms:
outputPlms.append(plm.multiply(objectPlm)) outputPlms.append(plm.multiply(objectPlm))
else: else:
outputShape = objectShape.copy() outputShape = ShapeCopy.copyShape(objectShape, copy_method_index, plm)
outputShape.Placement = plm.multiply(outputShape.Placement) #outputShape.Placement = plm.multiply(outputShape.Placement) # now handled by copyShape
outputShapes.append(outputShape) outputShapes.append(outputShape)
if outputIsLattice: if outputIsLattice:
@ -144,8 +150,7 @@ class LatticePopulateCopies(lattice2BaseFeature.LatticeFeature):
#now, set the result shape #now, set the result shape
if len(outputShapes) == 1 and obj.OutputCompounding == "only if many": if len(outputShapes) == 1 and obj.OutputCompounding == "only if many":
sh = outputShapes[0] sh = outputShapes[0]
sh.transformShape(sh.Placement.toMatrix(),True) #True = make copy sh = ShapeCopy.transformCopy(sh)
sh.Placement = App.Placement()
obj.Shape = sh obj.Shape = sh
else: else:
obj.Shape = Part.makeCompound(outputShapes) obj.Shape = Part.makeCompound(outputShapes)

87
lattice2ShapeCopy.py Normal file
View File

@ -0,0 +1,87 @@
#***************************************************************************
#* *
#* Copyright (c) 2016 - Victor Titov (DeepSOIC) *
#* <vv.titov@gmail.com> *
#* *
#* 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__="ShapeCopy module for Lattice2"
__author__ = "DeepSOIC"
__url__ = ""
__doc__ = "Utility methods to copy shapes"
import FreeCAD
def shallowCopy(shape, extra_placement = None):
"""shallowCopy(shape, extra_placement = None): creates a shallow copy of a shape. The
copy will match by isSame/isEqual/isPartner tests, but will have an independent placement."""
copiers = {
"Vertex": lambda(sh): sh.Vertexes[0],
"Edge": lambda(sh): sh.Edges[0],
"Wire": lambda(sh): sh.Wires[0],
"Face": lambda(sh): sh.Faces[0],
"Shell": lambda(sh): sh.Shells[0],
"Solid": lambda(sh): sh.Solids[0],
"CompSolid": lambda(sh): sh.CompSolids[0],
"Compound": lambda(sh): sh.Compounds[0],
}
copier = copiers.get(shape.ShapeType)
if copier is None:
copier = lambda(sh): sh.copy()
FreeCAD.Console.PrintWarning("Lattice2: shallowCopy: unexpected shape type '{typ}'. Using deep copy instead.\n".format(typ= shape.ShapeType))
ret = copier(shape)
if extra_placement is not None:
ret.Placement = extra_placement.multiply(ret.Placement)
return ret
def deepCopy(shape, extra_placement = None):
"""deepCopy(shape, extra_placement = None): Copies all subshapes. The copy will not match by isSame/isEqual/
isPartner tests."""
ret = shape.copy()
if extra_placement is not None:
ret.Placement = extra_placement.multiply(ret.Placement)
return ret
def transformCopy(shape, extra_placement = None):
"""transformCopy(shape, extra_placement = None): creates a deep copy shape with shape's placement applied to
the subelements (the placement of returned shape is zero)."""
if extra_placement is None:
extra_placement = FreeCAD.Placement()
ret = shape.copy()
ret.transformShape(extra_placement.multiply(ret.Placement).toMatrix(), True)
ret.Placement = FreeCAD.Placement() #reset placement
return ret
copy_types = ["Shallow copy", "Deep copy", "Transformed deep copy"]
copy_functions = [shallowCopy, deepCopy, transformCopy]
def getCopyTypeIndex(copy_type_string):
return copy_types.index(str(copy_type_string))
def copyShape(shape, copy_type_index, extra_placement = None):
"""copyShape(shape, copy_type_index, extra_placement = None): copies a shape (or creates
a moved copy of shape, if extra_placement is given). copy_type_index should be obtained
from string by getCopyTypeIndex() function."""
global copy_functions
return copy_functions[copy_type_index](shape, extra_placement)