Skip to content

Commit

Permalink
Merge pull request #409 from kbwbe/convertingParts
Browse files Browse the repository at this point in the history
Converting parts
  • Loading branch information
kbwbe authored Jan 24, 2021
2 parents c1d2465 + e306110 commit 343c0f6
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 109 deletions.
2 changes: 1 addition & 1 deletion InitGui.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
__title__ = 'A2plus assembly Workbench - InitGui file'
__author__ = 'kbwbe'

A2P_VERSION = 'V0.4.48a'
A2P_VERSION = 'V0.4.49'

import FreeCAD
import FreeCADGui
Expand Down
25 changes: 17 additions & 8 deletions a2p_constraints.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,10 +324,14 @@ def __init__(self,selection):

def calcInitialValues(self):
c = self.constraintObject
circleEdge1 = getObjectEdgeFromName(self.ob1, c.SubElement1)
circleEdge2 = getObjectEdgeFromName(self.ob2, c.SubElement2)
axis1 = circleEdge1.Curve.Axis
axis2 = circleEdge2.Curve.Axis
#circleEdge1 = getObjectEdgeFromName(self.ob1, c.SubElement1)
#circleEdge2 = getObjectEdgeFromName(self.ob2, c.SubElement2)
#axis1 = circleEdge1.Curve.Axis
#axis2 = circleEdge2.Curve.Axis
axis1 = getAxis(self.ob1, c.SubElement1)
axis2 = getAxis(self.ob2, c.SubElement2)


angle = math.degrees(axis1.getAngle(axis2))
if angle <= 90.0:
self.direction = "aligned"
Expand All @@ -340,10 +344,15 @@ def calcInitialValues(self):
def recalculateMatingDirection(c):
ob1 = c.Document.getObject(c.Object1)
ob2 = c.Document.getObject(c.Object2)
circleEdge1 = getObjectEdgeFromName(ob1, c.SubElement1)
circleEdge2 = getObjectEdgeFromName(ob2, c.SubElement2)
axis1 = circleEdge1.Curve.Axis
axis2 = circleEdge2.Curve.Axis
#circleEdge1 = getObjectEdgeFromName(ob1, c.SubElement1)
#circleEdge2 = getObjectEdgeFromName(ob2, c.SubElement2)
#axis1 = circleEdge1.Curve.Axis
#axis2 = circleEdge2.Curve.Axis

axis1 = getAxis(ob1, c.SubElement1)
axis2 = getAxis(ob2, c.SubElement2)


angle = math.degrees(axis1.getAngle(axis2))
if angle <= 90.0:
direction = "aligned"
Expand Down
145 changes: 85 additions & 60 deletions a2p_convertPart.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,50 @@
from a2p_importedPart_class import Proxy_convertPart # for compat.
from a2p_importedPart_class import ImportedPartViewProviderProxy # for compat.

from a2p_topomapper import TopoMapper



def updateConvertedPart(doc, obj):

obj.timeLastImport = time.time()

baseObject = doc.getObject(obj.localSourceObject)

savedPlacement = obj.Placement
obj.ViewObject.ShapeColor = baseObject.ViewObject.ShapeColor
topoMapper = TopoMapper(doc) # imports the objects and creates toponames if wanted
baseObject.ViewObject.Visibility = True #the topomapper ignores invisible shapes
obj.muxInfo, obj.Shape, obj.ViewObject.DiffuseColor, obj.ViewObject.Transparency = \
topoMapper.createTopoNames(desiredShapeLabel = baseObject.Label)
baseObject.ViewObject.Visibility = False #set baseObject invisible again.
obj.Placement = savedPlacement

for p in baseObject.ViewObject.PropertiesList:
if hasattr(baseObject.ViewObject, p) and p not in [
'DiffuseColor',
'Proxy',
'MappedColors',
'DisplayModeBody'
]:
try:
setattr(obj.ViewObject, p, getattr( baseObject.ViewObject, p))
except:
pass #a lot of attributes related e.g. to sketcher

if not a2plib.getPerFaceTransparency():
# switch of perFaceTransparency
obj.ViewObject.Transparency = 1
obj.ViewObject.Transparency = 0 # default = nontransparent

obj.recompute()
obj.ViewObject.Visibility = True

def convertToImportedPart(doc, obj):
'''
convertToImportedPart(document, documentObject) - changes a regular FreeCAD object into an A2plus
importedPart, adds the importedPart to the document and removes the FreeCAD object from the
document. Returns None
importedPart, adds the importedPart to the document and hides the original object from the
document. Updating the assembly will also update the converted part
'''
partName = a2plib.findUnusedObjectName( obj.Label, document=doc )
partLabel = a2plib.findUnusedObjectLabel( obj.Label, document=doc )
Expand All @@ -57,6 +95,7 @@ def convertToImportedPart(doc, obj):

newObj.a2p_Version = A2P_VERSION
newObj.sourceFile = filename
newObj.localSourceObject = obj.Name
#newObj.sourcePart = ""
newObj.setEditorMode("timeLastImport",1)
newObj.timeLastImport = time.time()
Expand All @@ -65,14 +104,26 @@ def convertToImportedPart(doc, obj):
newObj.setEditorMode("subassemblyImport",1)
newObj.updateColors = True

newObj.Shape = obj.Shape.copy()
newObj.muxInfo = createTopoInfo(obj)
newObj.ViewObject.ShapeColor = obj.ViewObject.ShapeColor

#-------------------------------------------
# Initialize the new TopoMapper
#-------------------------------------------
topoMapper = TopoMapper(doc)
newObj.muxInfo, newObj.Shape, newObj.ViewObject.DiffuseColor, newObj.ViewObject.Transparency = \
topoMapper.createTopoNames(desiredShapeLabel = obj.Label)

for p in obj.ViewObject.PropertiesList:
if hasattr(obj.ViewObject, p) and p not in ['DiffuseColor','Proxy','MappedColors','DisplayModeBody']:
setattr(newObj.ViewObject, p, getattr( obj.ViewObject, p))
newObj.ViewObject.ShapeColor = obj.ViewObject.ShapeColor
newObj.ViewObject.DiffuseColor = copy.copy( obj.ViewObject.DiffuseColor ) # diffuse needs to happen last
if hasattr(obj.ViewObject, p) and p not in [
'DiffuseColor',
'Proxy',
'MappedColors',
'DisplayModeBody'
]:
try:
setattr(newObj.ViewObject, p, getattr( obj.ViewObject, p))
except: #some sketcher attributes e.g.
pass

if not a2plib.getPerFaceTransparency():
# switch of perFaceTransparency
Expand All @@ -83,7 +134,7 @@ def convertToImportedPart(doc, obj):
newObj.Placement.Base = obj.Placement.Base
newObj.Placement.Rotation = obj.Placement.Rotation

doc.removeObject(obj.Name) # don't want the original in this doc anymore
obj.ViewObject.Visibility = False
newObj.recompute()


Expand All @@ -97,10 +148,9 @@ def convertToImportedPart(doc, obj):
can be applied. Also you can
duplicate the converted part.
(The shape of the converted part
is not editable anymore, as it
is a static copy of the original
shape.)
For editing a converted part,
hit the edit button and follow
the instructions shown on screen.
This function is useful, if
you want to use e.g. fasteners
Expand All @@ -119,58 +169,33 @@ def GetResources(self):
def Activated(self):
doc = FreeCAD.activeDocument()
selection = FreeCADGui.Selection.getSelection()
if not selection:
msg = \
'''
You must select a part to convert first.
'''
QtGui.QMessageBox.information(
QtGui.QApplication.activeWindow(),
"Selection Error",
msg
)
return
elif not selection[0].isDerivedFrom("Part::Feature"): # change here if allowing groups
msg = \
'''
Please select a Part.
'''
QtGui.QMessageBox.information(
QtGui.QApplication.activeWindow(),
"Selection Error",
msg
)
return

elif len(selection) > 1:
for s in selection:
if not s.isDerivedFrom("Part::Feature"): # change here if allowing groups
msg = \
'''
Please select a Part.
'''
QtGui.QMessageBox.information(
QtGui.QApplication.activeWindow(),
"Selection Error",
msg
)
return
else:
doc.openTransaction("part converted to A2plus")
convertToImportedPart(doc, s)
doc.commitTransaction()
else:
doc.openTransaction("part converted to A2plus")
convertToImportedPart(doc, selection[0])
for s in selection:
if s.ViewObject.Visibility == False:
msg = u"Please select only visible parts!"
QtGui.QMessageBox.information(
QtGui.QApplication.activeWindow(),
u"Conversion Aborted",
msg
)
return
for s in selection:
doc.openTransaction(u"part converted to A2plus")
convertToImportedPart(doc, s)
doc.commitTransaction()

def IsActive(self):
"""Here you can define if the command must be active or not (grayed out)
if certain conditions are met or not. This function is optional."""
if FreeCAD.activeDocument() is None:
return False

return True

selection = FreeCADGui.Selection.getSelection()
if not selection: return False
for s in selection:
if a2plib.isA2pPart(s): return False
if (
not s.isDerivedFrom("Part::Feature") and
not s.Name.startswith('Sketch')
):
return False
return True

FreeCADGui.addCommand('a2p_ConvertPart',a2p_ConvertPartCommand())
14 changes: 7 additions & 7 deletions a2p_dependencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,13 +167,13 @@ def Create(doc, constraint, solver, rigid1, rigid2):

ob1 = doc.getObject(c.Object1)
ob2 = doc.getObject(c.Object2)
circleEdge1 = getObjectEdgeFromName(ob1, c.SubElement1)
circleEdge2 = getObjectEdgeFromName(ob2, c.SubElement2)
dep1.refPoint = circleEdge1.Curve.Center
dep2.refPoint = circleEdge2.Curve.Center

axis1 = circleEdge1.Curve.Axis
axis2 = circleEdge2.Curve.Axis

dep1.refPoint = getPos(ob1, c.SubElement1)
dep2.refPoint = getPos(ob2, c.SubElement2)

axis1 = getAxis(ob1, c.SubElement1)
axis2 = getAxis(ob2, c.SubElement2)

if dep2.direction == "opposed":
axis2.multiply(-1.0)
dep1.refAxisEnd = dep1.refPoint.add(axis1)
Expand Down
2 changes: 2 additions & 0 deletions a2p_importedPart_class.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ def setProperties(self,obj):
obj.addProperty("App::PropertyFile", "sourceFile", "importPart")
if not "sourcePart" in propList:
obj.addProperty("App::PropertyString", "sourcePart", "importPart")
if not "localSourceObject" in propList:
obj.addProperty("App::PropertyString", "localSourceObject", "importPart")
if not "muxInfo" in propList:
obj.addProperty("App::PropertyStringList","muxInfo","importPart")
if not "timeLastImport" in propList:
Expand Down
73 changes: 42 additions & 31 deletions a2p_importpart.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,9 @@
import a2p_solversystem
from a2plib import getRelativePathesEnabled
import a2p_importedPart_class
import a2p_convertPart

from a2p_topomapper import (
TopoMapper
)
from a2p_topomapper import TopoMapper

import a2p_lcs_support
from a2p_importedPart_class import Proxy_importPart, ImportedPartViewProviderProxy
Expand Down Expand Up @@ -651,6 +650,11 @@ def updateImportedParts(doc, partial=False):
workingSet = doc.Objects

for obj in workingSet:
if hasattr(obj, 'sourceFile') and a2plib.to_str(obj.sourceFile) == a2plib.to_str('converted'):
if hasattr(obj,'localSourceObject') and obj.localSourceObject is not None and obj.localSourceObject != "":
a2p_convertPart.updateConvertedPart(doc, obj)
continue

if hasattr(obj, 'sourceFile') and a2plib.to_str(obj.sourceFile) != a2plib.to_str('converted'):


Expand Down Expand Up @@ -787,6 +791,7 @@ def duplicateImportedPart( part ):
newObj.a2p_Version = part.a2p_Version
newObj.sourceFile = part.sourceFile
newObj.sourcePart = part.sourcePart
newObj.localSourceObject = part.localSourceObject
newObj.timeLastImport = part.timeLastImport
newObj.setEditorMode("timeLastImport",1)
newObj.fixedPosition = False
Expand Down Expand Up @@ -891,39 +896,35 @@ def GetResources(self):
class a2p_EditPartCommand:
def Activated(self):
doc = FreeCAD.activeDocument()
#====================================================
# Is there an open Doc ?
#====================================================
if doc is None:
QtGui.QMessageBox.information( QtGui.QApplication.activeWindow(),
u"No active document found!",
u"Before editing a part, you have to open an assembly file."
)
return

#====================================================
# Is something been selected ?
#====================================================
selection = [s for s in FreeCADGui.Selection.getSelection() if s.Document == FreeCAD.ActiveDocument ]
if not selection:
QtGui.QMessageBox.information(
QtGui.QApplication.activeWindow(),
u"Selection Error",
u"You must select a part to edit first."
)
return


#====================================================
# Has the selected object an editable a2p file ?
# Do we deal with a converted Part ?
#====================================================
obj = selection[0]
if not a2plib.isEditableA2pPart(obj):
QtGui.QMessageBox.information( QtGui.QApplication.activeWindow(),
u"Edit: Selection invalid!",
u"This object is no imported part!"
)
if obj.sourceFile == 'converted':
try:
originalPart = doc.getObject(obj.localSourceObject)
FreeCADGui.Selection.clearSelection()
FreeCADGui.Selection.addSelection(originalPart)

QtGui.QMessageBox.information(
QtGui.QApplication.activeWindow(),
u"Information ",
u"Please edit the highlighted object.\nWhen finished, update the assembly"
)
return
except:
pass
QtGui.QMessageBox.critical(
QtGui.QApplication.activeWindow(),
u"File error ! ",
u"Cannot find the local source object.\nHas it been deleted?"
)
return




#====================================================
# Does the file exist ?
#====================================================
Expand Down Expand Up @@ -983,6 +984,16 @@ def Activated(self):
mdi.setActiveSubWindow(s)
if FreeCAD.activeDocument().Name == name: break

def IsActive(self):
doc = FreeCAD.activeDocument()
if doc is None: return False

selection = [s for s in FreeCADGui.Selection.getSelection() if s.Document == FreeCAD.ActiveDocument ]
if len(selection) != 1: return False

if not a2plib.isEditableA2pPart(selection[0]): return False

return True

def GetResources(self):
return {
Expand Down
Loading

0 comments on commit 343c0f6

Please sign in to comment.