From 4f13da61e7cc51a69415c6f01cc8e5a544bc2ebf Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 4 Feb 2013 23:42:22 -0200 Subject: [PATCH 1/8] Arch: small tweaks to ifc importer --- src/Mod/Arch/importIFC.py | 38 ++++++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index 19b22a5794..18ea08047e 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -140,41 +140,45 @@ def read(filename): # retrieving name n = obj.name if not n: - n = "Unnamed" + n = "" # build shape shape = None if useShapes: shape = getShape(obj) - + # skip types if obj.type in SKIP: pass # walls elif obj.type == "IfcWallStandardCase": - makeWall(ifc.Entities[obj.id],shape) + makeWall(ifc.Entities[obj.id],shape,n) # windows elif obj.type in ["IfcWindow","IfcDoor"]: - makeWindow(ifc.Entities[obj.id],shape) + makeWindow(ifc.Entities[obj.id],shape,n) # structs - elif obj.type in ["IfcBeam","IfcColumn","IfcSlab"]: - makeStructure(ifc.Entities[obj.id],shape) + elif obj.type in ["IfcBeam","IfcColumn","IfcSlab","IfcFooting"]: + makeStructure(ifc.Entities[obj.id],shape,n) # furniture elif obj.type == "IfcFurnishingElement": - nobj = FreeCAD.ActiveDocument.addObject("Part::Feature","Furniture") + nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj.Shape = shape elif shape: # treat as dumb parts + if not n: + n = "Unnamed" nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) nobj.Shape = shape else: # treat as meshes + if not n: + n = "Unnamed" me,pl = getMesh(obj) nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n) nobj.Mesh = me @@ -250,6 +254,7 @@ def group(entity,mode=None): ['Window','IfcWindow',[]], ['Door','IfcDoor',[]], ['Slab','IfcSlab',[]], + ['Footing','IfcFooting',[]], ['Beam','IfcBeam',[]], ['Column','IfcColumn',[]], ['Floor','IfcBuildingStorey',[]], @@ -280,17 +285,21 @@ def group(entity,mode=None): for g in groups: comps.extend(g[2]) + label = entity.Name name = mode + str(entity.id) + cell = None if mode == "Site": cell = Arch.makeSite(comps,name=name) elif mode == "Floor": cell = Arch.makeFloor(comps,name=name) elif mode == "Building": cell = Arch.makeBuilding(comps,name=name) + if label and cell: + cell.Label = label except: if DEBUG: print "error: skipping group ",entity.id -def makeWall(entity,shape=None): +def makeWall(entity,shape=None,name=None): "makes a wall in the freecad document" try: if DEBUG: print "=====> making wall",entity.id @@ -298,6 +307,7 @@ def makeWall(entity,shape=None): sh = FreeCAD.ActiveDocument.addObject("Part::Feature","WallBody") sh.Shape = shape wall = Arch.makeWall(sh,name="Wall"+str(entity.id)) + wall.Label = name if DEBUG: print "made wall object ",entity.id,":",wall return placement = wall = wire = body = width = height = None @@ -311,6 +321,8 @@ def makeWall(entity,shape=None): if r.RepresentationIdentifier == "Axis": wire = getWire(r.Items,placement) wall = Arch.makeWall(wire,width,height,align="Center",name="Wall"+str(entity.id)) + if name: + wall.Label = name else: if DEBUG: print "no height or width properties found..." for r in entity.Representation.Representations: @@ -327,7 +339,7 @@ def makeWall(entity,shape=None): except: if DEBUG: print "error: skipping wall",entity.id -def makeWindow(entity,shape=None): +def makeWindow(entity,shape=None,name=""): "makes a window in the freecad document" try: typ = "Window" if entity.type == "IFCWINDOW" else "Door" @@ -335,6 +347,8 @@ def makeWindow(entity,shape=None): if shape: window = Arch.makeWindow(name=typ+str(entity.id)) window.Shape = shape + if name: + window.Label = name if DEBUG: print "made window object ",entity.id,":",window return placement = window = wire = body = width = height = None @@ -353,13 +367,15 @@ def makeWindow(entity,shape=None): except: if DEBUG: print "error: skipping window",entity.id -def makeStructure(entity,shape=None): +def makeStructure(entity,shape=None,name=""): "makes a structure in the freecad document" try: if entity.type == "IFCSLAB": typ = "Slab" elif entity.type == "IFCBEAM": typ = "Beam" + elif entity.type == "IFCFOOTING": + typ = "Footing" else: typ = "Column" @@ -368,6 +384,8 @@ def makeStructure(entity,shape=None): sh = FreeCAD.ActiveDocument.addObject("Part::Feature","StructureBody") sh.Shape = shape structure = Arch.makeStructure(sh,name=typ+str(entity.id)) + if name: + structure.Label = name if DEBUG: print "made structure object ",entity.id,":",structure return placement = structure = wire = body = width = height = None From 3ec00739334275c4d728f2c1e1a6e1b578041a3a Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Tue, 5 Feb 2013 14:24:21 -0200 Subject: [PATCH 2/8] Arch: Added terrain property to Site objects --- src/Mod/Arch/ArchSite.py | 5 ++ src/Mod/Arch/importIFC.py | 101 +++++++++++++++++++++++++------------- 2 files changed, 73 insertions(+), 33 deletions(-) diff --git a/src/Mod/Arch/ArchSite.py b/src/Mod/Arch/ArchSite.py index f6c6e9acbb..0626054d0c 100644 --- a/src/Mod/Arch/ArchSite.py +++ b/src/Mod/Arch/ArchSite.py @@ -80,6 +80,8 @@ class _Site(ArchFloor._Floor): "The Site object" def __init__(self,obj): ArchFloor._Floor.__init__(self,obj) + obj.addProperty("App::PropertyLink","Terrain","Base", + str(translate("Arch","The terrain of this site"))) self.Type = "Site" obj.setEditorMode('Height',2) @@ -91,6 +93,9 @@ class _ViewProviderSite(ArchFloor._ViewProviderFloor): def getIcon(self): import Arch_rc return ":/icons/Arch_Site_Tree.svg" + + def claimChildren(self): + return self.Object.Group+[self.Object.Terrain] FreeCADGui.addCommand('Arch_Site',_CommandSite()) diff --git a/src/Mod/Arch/importIFC.py b/src/Mod/Arch/importIFC.py index 18ea08047e..c3cedfe3c8 100644 --- a/src/Mod/Arch/importIFC.py +++ b/src/Mod/Arch/importIFC.py @@ -113,6 +113,7 @@ def read(filename): # parsing the IFC file t1 = time.time() schema=getSchema() + ifcRel = {} if schema: if DEBUG: global ifc if DEBUG: print "opening",filename,"..." @@ -153,16 +154,16 @@ def read(filename): # walls elif obj.type == "IfcWallStandardCase": - makeWall(ifc.Entities[obj.id],shape,n) + nobj = makeWall(ifc.Entities[obj.id],shape,n) # windows elif obj.type in ["IfcWindow","IfcDoor"]: - makeWindow(ifc.Entities[obj.id],shape,n) + nobj = makeWindow(ifc.Entities[obj.id],shape,n) # structs elif obj.type in ["IfcBeam","IfcColumn","IfcSlab","IfcFooting"]: - makeStructure(ifc.Entities[obj.id],shape,n) - + nobj = makeStructure(ifc.Entities[obj.id],shape,n) + # furniture elif obj.type == "IfcFurnishingElement": nobj = FreeCAD.ActiveDocument.addObject("Part::Feature",n) @@ -183,6 +184,14 @@ def read(filename): nobj = FreeCAD.ActiveDocument.addObject("Mesh::Feature",n) nobj.Mesh = me nobj.Placement = pl + + ifcRel[obj.id] = nobj + + # mark terrain objects so they can be associated to sites + if obj.type == "IfcSite": + if not "terrains" in ifcRel: + ifcRel["terrains"] = [] + ifcRel["terrains"].append([obj.id,nobj]) if not IfcImport.Next(): break @@ -194,37 +203,41 @@ def read(filename): # getting walls for w in ifc.getEnt("IfcWallStandardCase"): - makeWall(w) + nobj = makeWall(w) + ifcRel[w.id] = nobj # getting windows and doors for w in (ifc.getEnt("IfcWindow") + ifc.getEnt("IfcDoor")): - makeWindow(w) + nobj = makeWindow(w) + ifcRel[w.id] = nobj # getting structs - for w in (ifc.getEnt("IfcSlab") + ifc.getEnt("IfcBeam") + ifc.getEnt("IfcColumn")): - makeStructure(w) + for w in (ifc.getEnt("IfcSlab") + ifc.getEnt("IfcBeam") + ifc.getEnt("IfcColumn") \ + + ifc.getEnt("IfcFooting")): + nobj = makeStructure(w) + ifcRel[w.id] = nobj - order(ifc) + order(ifc,ifcRel) FreeCAD.ActiveDocument.recompute() t3 = time.time() if DEBUG: print "done processing",ifc,"in %s s" % ((t3-t1)) return None -def order(ifc): +def order(ifc,ifcRel): "orders the already generated elements by building and by floor" # getting floors for f in ifc.getEnt("IfcBuildingStorey"): - group(f,"Floor") + group(f,ifcRel,"Floor") # getting buildings for b in ifc.getEnt("IfcBuilding"): - group(b,"Building") + group(b,ifcRel,"Building") # getting sites for s in ifc.getEnt("IfcSite"): - group(s,"Site") + group(s,ifcRel,"Site") -def group(entity,mode=None): +def group(entity,ifcRel,mode=None): "gathers the children of the given entity" try: @@ -250,23 +263,21 @@ def group(entity,mode=None): elts.extend(s) print "found dependent elements: ",elts - groups = [['Wall','IfcWallStandardCase',[]], - ['Window','IfcWindow',[]], - ['Door','IfcDoor',[]], - ['Slab','IfcSlab',[]], - ['Footing','IfcFooting',[]], - ['Beam','IfcBeam',[]], - ['Column','IfcColumn',[]], - ['Floor','IfcBuildingStorey',[]], - ['Building','IfcBuilding',[]], - ['Furniture','IfcFurnishingElement',[]]] + groups = [['Wall',['IfcWallStandardCase'],[]], + ['Window',['IfcWindow','IfcDoor'],[]], + ['Structure',['IfcSlab','IfcFooting','IfcBeam','IfcColumn'],[]], + ['Floor',['IfcBuildingStorey'],[]], + ['Building',['IfcBuilding'],[]], + ['Furniture',['IfcFurnishingElement'],[]]] for e in elts: for g in groups: - if e.type.upper() == g[1].upper(): - o = FreeCAD.ActiveDocument.getObject(g[0] + str(e.id)) - if o: - g[2].append(o) + for t in g[1]: + if e.type.upper() == t.upper(): + if e.id in ifcRel: + g[2].append(ifcRel[e.id]) + elif hasattr(FreeCAD.ActiveDocument,g[0]+str(e.id)): + g[2].append(FreeCAD.ActiveDocument.getObject(g[0]+str(e.id))) print "groups:",groups comps = [] @@ -290,6 +301,12 @@ def group(entity,mode=None): cell = None if mode == "Site": cell = Arch.makeSite(comps,name=name) + # add terrain object + if "terrains" in ifcRel: + for t in ifcRel["terrains"]: + if t[0] == entity.id: + if not t[1] in comps: + cell.Terrain = t[1] elif mode == "Floor": cell = Arch.makeFloor(comps,name=name) elif mode == "Building": @@ -304,12 +321,14 @@ def makeWall(entity,shape=None,name=None): try: if DEBUG: print "=====> making wall",entity.id if shape: + # use ifcopenshell sh = FreeCAD.ActiveDocument.addObject("Part::Feature","WallBody") sh.Shape = shape wall = Arch.makeWall(sh,name="Wall"+str(entity.id)) wall.Label = name if DEBUG: print "made wall object ",entity.id,":",wall - return + return wall + # use internal parser placement = wall = wire = body = width = height = None placement = getPlacement(entity.ObjectPlacement) if DEBUG: print "got wall placement",entity.id,":",placement @@ -336,8 +355,13 @@ def makeWall(entity,shape=None,name=None): wall.Normal = norm if wall: if DEBUG: print "made wall object ",entity.id,":",wall + return wall + if DEBUG: print "error: skipping wall",entity.id + return None except: if DEBUG: print "error: skipping wall",entity.id + return None + def makeWindow(entity,shape=None,name=""): "makes a window in the freecad document" @@ -345,12 +369,14 @@ def makeWindow(entity,shape=None,name=""): typ = "Window" if entity.type == "IFCWINDOW" else "Door" if DEBUG: print "=====> making window",entity.id if shape: + # use ifcopenshell window = Arch.makeWindow(name=typ+str(entity.id)) window.Shape = shape if name: window.Label = name if DEBUG: print "made window object ",entity.id,":",window - return + return window + # use internal parser placement = window = wire = body = width = height = None placement = getPlacement(entity.ObjectPlacement) if DEBUG: print "got window placement",entity.id,":",placement @@ -364,8 +390,12 @@ def makeWindow(entity,shape=None,name=""): window = Arch.makeWindow(wire,width=b.Depth,name=typ+str(entity.id)) if window: if DEBUG: print "made window object ",entity.id,":",window + return window + if DEBUG: print "error: skipping window",entity.id + return None except: if DEBUG: print "error: skipping window",entity.id + return None def makeStructure(entity,shape=None,name=""): "makes a structure in the freecad document" @@ -381,13 +411,15 @@ def makeStructure(entity,shape=None,name=""): if DEBUG: print "=====> making struct",entity.id if shape: + # use ifcopenshell sh = FreeCAD.ActiveDocument.addObject("Part::Feature","StructureBody") sh.Shape = shape structure = Arch.makeStructure(sh,name=typ+str(entity.id)) if name: structure.Label = name if DEBUG: print "made structure object ",entity.id,":",structure - return + return structure + # use internal parser placement = structure = wire = body = width = height = None placement = getPlacement(entity.ObjectPlacement) if DEBUG: print "got window placement",entity.id,":",placement @@ -401,10 +433,13 @@ def makeStructure(entity,shape=None,name=""): structure = Arch.makeStructure(wire,height=b.Depth,name=typ+str(entity.id)) if structure: if DEBUG: print "made structure object ",entity.id,":",structure + return structure + if DEBUG: print "error: skipping structure",entity.id + return None except: if DEBUG: print "error: skipping structure",entity.id - - + return None + # geometry helpers ################################################################### def getMesh(obj): From 135f534ff603ce0c7a5356b50fd67810a62d61d3 Mon Sep 17 00:00:00 2001 From: logari81 Date: Wed, 13 Feb 2013 12:18:31 +0100 Subject: [PATCH 3/8] Part: Avoid code duplication in Part2DObject --- src/Mod/Part/App/Part2DObject.cpp | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/Mod/Part/App/Part2DObject.cpp b/src/Mod/Part/App/Part2DObject.cpp index ecdefd60d6..9d6d324e34 100644 --- a/src/Mod/Part/App/Part2DObject.cpp +++ b/src/Mod/Part/App/Part2DObject.cpp @@ -162,30 +162,10 @@ void Part2DObject::positionBySupport(void) gp_Trsf Trf; Trf.SetTransformation(SketchPos); Trf.Invert(); + Trf.SetScaleFactor(Standard_Real(1.0)); Base::Matrix4D mtrx; - - gp_Mat m = Trf._CSFDB_Getgp_Trsfmatrix(); - gp_XYZ p = Trf._CSFDB_Getgp_Trsfloc(); - Standard_Real scale = 1.0; - - // set Rotation matrix - mtrx[0][0] = scale * m._CSFDB_Getgp_Matmatrix(0,0); - mtrx[0][1] = scale * m._CSFDB_Getgp_Matmatrix(0,1); - mtrx[0][2] = scale * m._CSFDB_Getgp_Matmatrix(0,2); - - mtrx[1][0] = scale * m._CSFDB_Getgp_Matmatrix(1,0); - mtrx[1][1] = scale * m._CSFDB_Getgp_Matmatrix(1,1); - mtrx[1][2] = scale * m._CSFDB_Getgp_Matmatrix(1,2); - - mtrx[2][0] = scale * m._CSFDB_Getgp_Matmatrix(2,0); - mtrx[2][1] = scale * m._CSFDB_Getgp_Matmatrix(2,1); - mtrx[2][2] = scale * m._CSFDB_Getgp_Matmatrix(2,2); - - // set pos vector - mtrx[0][3] = p._CSFDB_Getgp_XYZx(); - mtrx[1][3] = p._CSFDB_Getgp_XYZy(); - mtrx[2][3] = p._CSFDB_Getgp_XYZz(); + TopoShape::convertToMatrix(Trf,mtrx); // check the angle against the Z Axis //Standard_Real a = Normal.Angle(gp_Ax1(gp_Pnt(0,0,0),gp_Dir(0,0,1))); From e2ae103edf3c52022d25bec47c9d157b3ba2feec Mon Sep 17 00:00:00 2001 From: logari81 Date: Wed, 13 Feb 2013 12:24:12 +0100 Subject: [PATCH 4/8] PartDesign: Remove unnecessary updateActive calls from creating pattern commands --- src/Mod/PartDesign/Gui/Command.cpp | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 99d7cf1fe2..975412ab9d 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -902,7 +902,6 @@ void CmdPartDesignMirrored::activated(int iMsg) for (std::vector::iterator it = tempSelNames.begin(); it != tempSelNames.end(); ++it) doCommand(Gui,"Gui.activeDocument().%s.Visibility=False",it->c_str()); - updateActive(); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); @@ -970,16 +969,15 @@ void CmdPartDesignLinearPattern::activated(int iMsg) doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::LinearPattern\",\"%s\")",FeatName.c_str()); updateActive(); doCommand(Doc,str.str().c_str()); - Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(); + Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(); if (sketch) - doCommand(Doc,"App.activeDocument().%s.Direction = (App.activeDocument().%s, [\"H_Axis\"])", + doCommand(Doc,"App.activeDocument().%s.Direction = (App.activeDocument().%s, [\"H_Axis\"])", FeatName.c_str(), sketch->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.Length = 100", FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Occurrences = 2", FeatName.c_str()); for (std::vector::iterator it = tempSelNames.begin(); it != tempSelNames.end(); ++it) doCommand(Gui,"Gui.activeDocument().%s.Visibility=False",it->c_str()); - updateActive(); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); @@ -1047,16 +1045,15 @@ void CmdPartDesignPolarPattern::activated(int iMsg) doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::PolarPattern\",\"%s\")",FeatName.c_str()); updateActive(); doCommand(Doc,str.str().c_str()); - Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(); + Part::Part2DObject *sketch = (static_cast(features.front()))->getVerifiedSketch(); if (sketch) - doCommand(Doc,"App.activeDocument().%s.Axis = (App.activeDocument().%s, [\"N_Axis\"])", + doCommand(Doc,"App.activeDocument().%s.Axis = (App.activeDocument().%s, [\"N_Axis\"])", FeatName.c_str(), sketch->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.Angle = 360", FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Occurrences = 2", FeatName.c_str()); for (std::vector::iterator it = tempSelNames.begin(); it != tempSelNames.end(); ++it) doCommand(Gui,"Gui.activeDocument().%s.Visibility=False",it->c_str()); - updateActive(); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); @@ -1129,7 +1126,6 @@ void CmdPartDesignScaled::activated(int iMsg) for (std::vector::iterator it = tempSelNames.begin(); it != tempSelNames.end(); ++it) doCommand(Gui,"Gui.activeDocument().%s.Visibility=False",it->c_str()); - updateActive(); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); @@ -1198,7 +1194,6 @@ void CmdPartDesignMultiTransform::activated(int iMsg) updateActive(); doCommand(Doc,str.str().c_str()); - updateActive(); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); copyVisual(FeatName.c_str(), "ShapeColor", tempSelNames.front().c_str()); From ebb91821415758c1ff7de1897d7fe8e3e2f50069 Mon Sep 17 00:00:00 2001 From: logari81 Date: Wed, 13 Feb 2013 14:06:36 +0100 Subject: [PATCH 5/8] PartDesign: Highlight in red the rejected transformations when editing pattern features --- .../Gui/ViewProviderLinearPattern.cpp | 2 + .../PartDesign/Gui/ViewProviderMirrored.cpp | 2 + .../Gui/ViewProviderMultiTransform.cpp | 2 + .../Gui/ViewProviderPolarPattern.cpp | 2 + src/Mod/PartDesign/Gui/ViewProviderScaled.cpp | 2 + .../Gui/ViewProviderTransformed.cpp | 263 +++++++++++++++++- .../PartDesign/Gui/ViewProviderTransformed.h | 16 +- 7 files changed, 285 insertions(+), 4 deletions(-) diff --git a/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.cpp b/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.cpp index 393b9f2bfe..cb0e256a96 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderLinearPattern.cpp @@ -40,6 +40,8 @@ PROPERTY_SOURCE(PartDesignGui::ViewProviderLinearPattern,PartDesignGui::ViewProv bool ViewProviderLinearPattern::setEdit(int ModNum) { + ViewProviderTransformed::setEdit(ModNum); + if (ModNum == ViewProvider::Default ) { TaskDlgLinearPatternParameters *linearpatternDlg = NULL; diff --git a/src/Mod/PartDesign/Gui/ViewProviderMirrored.cpp b/src/Mod/PartDesign/Gui/ViewProviderMirrored.cpp index 4bb9c794dc..dece48ea21 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderMirrored.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderMirrored.cpp @@ -40,6 +40,8 @@ PROPERTY_SOURCE(PartDesignGui::ViewProviderMirrored,PartDesignGui::ViewProvider) bool ViewProviderMirrored::setEdit(int ModNum) { + ViewProviderTransformed::setEdit(ModNum); + if (ModNum == ViewProvider::Default ) { TaskDlgMirroredParameters *mirroredDlg = NULL; diff --git a/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.cpp b/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.cpp index 3c17680adc..839e28ff00 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderMultiTransform.cpp @@ -40,6 +40,8 @@ PROPERTY_SOURCE(PartDesignGui::ViewProviderMultiTransform,PartDesignGui::ViewPro bool ViewProviderMultiTransform::setEdit(int ModNum) { + ViewProviderTransformed::setEdit(ModNum); + if (ModNum == ViewProvider::Default ) { TaskDlgMultiTransformParameters *multitransformDlg = NULL; diff --git a/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.cpp b/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.cpp index 48bc5d7191..cafefd54d9 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderPolarPattern.cpp @@ -40,6 +40,8 @@ PROPERTY_SOURCE(PartDesignGui::ViewProviderPolarPattern,PartDesignGui::ViewProvi bool ViewProviderPolarPattern::setEdit(int ModNum) { + ViewProviderTransformed::setEdit(ModNum); + if (ModNum == ViewProvider::Default ) { TaskDlgPolarPatternParameters *polarpatternDlg = NULL; diff --git a/src/Mod/PartDesign/Gui/ViewProviderScaled.cpp b/src/Mod/PartDesign/Gui/ViewProviderScaled.cpp index b704f47161..61df00ca49 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderScaled.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderScaled.cpp @@ -40,6 +40,8 @@ PROPERTY_SOURCE(PartDesignGui::ViewProviderScaled,PartDesignGui::ViewProvider) bool ViewProviderScaled::setEdit(int ModNum) { + ViewProviderTransformed::setEdit(ModNum); + if (ModNum == ViewProvider::Default ) { TaskDlgScaledParameters *scaledDlg = NULL; diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp index 5af43cd05f..43e991b22c 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp @@ -24,15 +24,34 @@ #include "PreCompiled.h" #ifndef _PreComp_ +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include +# include #endif #include "ViewProviderTransformed.h" #include "TaskTransformedParameters.h" -#include -#include +#include #include -#include #include +#include +#include +#include +#include using namespace PartDesignGui; @@ -46,6 +65,64 @@ void ViewProviderTransformed::setupContextMenu(QMenu* menu, QObject* receiver, c PartGui::ViewProviderPart::setupContextMenu(menu, receiver, member); } +bool ViewProviderTransformed::setEdit(int ModNum) +{ + pcRejectedRoot = new SoSeparator(); + pcRejectedRoot->ref(); + + rejectedTrfms = new SoMultipleCopy(); + rejectedTrfms->ref(); + + rejectedCoords = new SoCoordinate3(); + rejectedCoords->ref(); + + rejectedNorms = new SoNormal(); + rejectedNorms->ref(); + + rejectedFaceSet = new SoIndexedFaceSet(); + rejectedFaceSet->ref(); + + SoPickStyle* rejectedPickStyle = new SoPickStyle(); + rejectedPickStyle->style = SoPickStyle::UNPICKABLE; + + SoShapeHints* rejectedHints = new SoShapeHints(); + rejectedHints->vertexOrdering = SoShapeHints::COUNTERCLOCKWISE; + rejectedHints->shapeType = SoShapeHints::UNKNOWN_SHAPE_TYPE; + + SoMaterialBinding* rejectedBind = new SoMaterialBinding(); + + SoTransparencyType* rejectedTransparencyType = new SoTransparencyType(); + rejectedTransparencyType->value.setValue(SoGLRenderAction::BLEND); + + SoMaterial* rejectedMaterial = new SoMaterial(); + rejectedMaterial->diffuseColor.set1Value(0,SbColor(1.f,0.f,0.f)); + rejectedMaterial->transparency.setValue(0.6f); + + SoDrawStyle* rejectedFaceStyle = new SoDrawStyle(); + rejectedFaceStyle->style = SoDrawStyle::FILLED; + + SoNormalBinding* rejectedNormb = new SoNormalBinding(); + rejectedNormb->value = SoNormalBinding::PER_VERTEX_INDEXED; + + // just faces with no edges or points + pcRejectedRoot->addChild(rejectedPickStyle); + pcRejectedRoot->addChild(rejectedTransparencyType); + pcRejectedRoot->addChild(rejectedBind); + pcRejectedRoot->addChild(rejectedMaterial); + pcRejectedRoot->addChild(rejectedHints); + pcRejectedRoot->addChild(rejectedFaceStyle); + pcRejectedRoot->addChild(rejectedCoords); + pcRejectedRoot->addChild(rejectedNorms); + pcRejectedRoot->addChild(rejectedNormb); + pcRejectedRoot->addChild(rejectedTrfms); + rejectedTrfms->addChild(rejectedFaceSet); + + pcRoot->addChild(pcRejectedRoot); + + recomputeFeature(); + return true; +} + void ViewProviderTransformed::unsetEdit(int ModNum) { if (ModNum == ViewProvider::Default) { @@ -55,6 +132,17 @@ void ViewProviderTransformed::unsetEdit(int ModNum) else { PartGui::ViewProviderPart::unsetEdit(ModNum); } + + rejectedTrfms->removeAllChildren(); + pcRejectedRoot->removeAllChildren(); + + pcRoot->removeChild(pcRejectedRoot); + + pcRejectedRoot->unref(); + rejectedTrfms->unref(); + rejectedCoords->unref(); + rejectedNorms->unref(); + rejectedFaceSet->unref(); } bool ViewProviderTransformed::onDelete(const std::vector &) @@ -126,5 +214,174 @@ void ViewProviderTransformed::recomputeFeature(void) msg = msg.arg(QObject::tr("Transformation succeeded")); } signalDiagnosis(msg); + + TopoDS_Shape shape; + if (rejected != 0) { + // FIXME: create a compound if there are more than one originals + App::DocumentObject* original = pcTransformed->Originals.getValues().front(); + if (original->getTypeId().isDerivedFrom(PartDesign::Additive::getClassTypeId())) { + PartDesign::Additive* addFeature = static_cast(original); + shape = addFeature->AddShape.getShape()._Shape; + } else if (original->getTypeId().isDerivedFrom(PartDesign::Subtractive::getClassTypeId())) { + PartDesign::Subtractive* subFeature = static_cast(original); + shape = subFeature->SubShape.getShape()._Shape; + } + } + + if (rejected == 0 || shape.IsNull()) { + rejectedCoords ->point .setNum(0); + rejectedNorms ->vector .setNum(0); + rejectedFaceSet ->coordIndex .setNum(0); + rejectedTrfms ->matrix .setNum(0); + } else { + // Display the rejected transformations in red + TopoDS_Shape cShape(shape); + + try { + // calculating the deflection value + Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; + { + Bnd_Box bounds; + BRepBndLib::Add(cShape, bounds); + bounds.SetGap(0.0); + bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); + } + Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); + + // create or use the mesh on the data structure + BRepMesh_IncrementalMesh myMesh(cShape,deflection); + // We must reset the location here because the transformation data + // are set in the placement property + TopLoc_Location aLoc; + cShape.Location(aLoc); + + // count triangles and nodes in the mesh + int nbrTriangles=0, nbrNodes=0; + TopExp_Explorer Ex; + for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { + Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); + // Note: we must also count empty faces + if (!mesh.IsNull()) { + nbrTriangles += mesh->NbTriangles(); + nbrNodes += mesh->NbNodes(); + } + } + + // create memory for the nodes and indexes + rejectedCoords ->point .setNum(nbrNodes); + rejectedNorms ->vector .setNum(nbrNodes); + rejectedFaceSet ->coordIndex .setNum(nbrTriangles*4); + + // get the raw memory for fast fill up + SbVec3f* verts = rejectedCoords ->point .startEditing(); + SbVec3f* norms = rejectedNorms ->vector .startEditing(); + int32_t* index = rejectedFaceSet ->coordIndex .startEditing(); + + // preset the normal vector with null vector + for (int i=0; i < nbrNodes; i++) + norms[i]= SbVec3f(0.0,0.0,0.0); + + int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0; + for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { + TopLoc_Location aLoc; + const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); + // get the mesh of the shape + Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); + if (mesh.IsNull()) continue; + + // getting the transformation of the shape/face + gp_Trsf myTransf; + Standard_Boolean identity = true; + if (!aLoc.IsIdentity()) { + identity = false; + myTransf = aLoc.Transformation(); + } + + // getting size of node and triangle array of this face + int nbNodesInFace = mesh->NbNodes(); + int nbTriInFace = mesh->NbTriangles(); + // check orientation + TopAbs_Orientation orient = actFace.Orientation(); + + // cycling through the poly mesh + const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); + const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); + for (int g=1; g <= nbTriInFace; g++) { + // Get the triangle + Standard_Integer N1,N2,N3; + Triangles(g).Get(N1,N2,N3); + + // change orientation of the triangle if the face is reversed + if ( orient != TopAbs_FORWARD ) { + Standard_Integer tmp = N1; + N1 = N2; + N2 = tmp; + } + + // get the 3 points of this triangle + gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); + + // transform the vertices to the place of the face + if (!identity) { + V1.Transform(myTransf); + V2.Transform(myTransf); + V3.Transform(myTransf); + } + + // calculating per vertex normals + // Calculate triangle normal + gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); + gp_Vec Normal = (v2-v1)^(v3-v1); + + // add the triangle normal to the vertex normal for all points of this triangle + norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); + norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); + norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); + + // set the vertices + verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); + verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); + verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); + + // set the index vector with the 3 point indexes and the end delimiter + index[FaceTriaOffset*4+4*(g-1)] = FaceNodeOffset+N1-1; + index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1; + index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1; + index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; + } + + // counting up the per Face offsets + FaceNodeOffset += nbNodesInFace; + FaceTriaOffset += nbTriInFace; + } + + // normalize all normals + for (int i=0; i < nbrNodes; i++) + norms[i].normalize(); + + // end the editing of the nodes + rejectedCoords ->point .finishEditing(); + rejectedNorms ->vector .finishEditing(); + rejectedFaceSet ->coordIndex .finishEditing(); + + // fill in the transformation matrices + rejectedTrfms->matrix.setNum(rejected); + SbMatrix* mats = rejectedTrfms->matrix.startEditing(); + + std::list rejected_trsf = pcTransformed->getRejectedTransformations(); + std::list::const_iterator trsf = rejected_trsf.begin(); + for (int i=0; i < rejected; i++,trsf++) { + Base::Matrix4D mat; + Part::TopoShape::convertToMatrix(*trsf,mat); + mats[i] = convert(mat); + } + rejectedTrfms->matrix.finishEditing(); + } + catch (...) { + Base::Console().Error("Cannot compute Inventor representation for the rejected transformations of shape of %s.\n", + pcTransformed->getNameInDocument()); + } + } + } diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.h b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h index 1265f67e8a..601df79b6e 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.h +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h @@ -26,6 +26,12 @@ #include "ViewProvider.h" +class SoCoordinate3; +class SoIndexedFaceSet; +class SoMultipleCopy; +class SoNormal; +class SoSeparator; + namespace PartDesignGui { class TaskDlgTransformedParameters; @@ -53,10 +59,18 @@ public: std::string featureName; protected: - virtual bool setEdit(int ModNum) { return false; } + virtual bool setEdit(int ModNum); virtual void unsetEdit(int ModNum); const bool checkDlgOpen(TaskDlgTransformedParameters* transformedDlg); + + // nodes for the representation of rejected repetitions + SoGroup * pcRejectedRoot; + SoMultipleCopy * rejectedTrfms; + SoCoordinate3 * rejectedCoords; + SoNormal * rejectedNorms; + SoIndexedFaceSet * rejectedFaceSet; + public: void recomputeFeature(); }; From ab5f7ab334a0182423ad7b2ad8f2dfaa11af9fc6 Mon Sep 17 00:00:00 2001 From: jrheinlaender Date: Thu, 14 Feb 2013 00:03:58 +0100 Subject: [PATCH 6/8] PartDesign: Add method suggesting Groove Reversed property so that material is always removed from the support --- src/Mod/PartDesign/App/FeatureGroove.cpp | 38 ++++++++++++++++++++++++ src/Mod/PartDesign/App/FeatureGroove.h | 2 ++ 2 files changed, 40 insertions(+) diff --git a/src/Mod/PartDesign/App/FeatureGroove.cpp b/src/Mod/PartDesign/App/FeatureGroove.cpp index 006abdeeac..3cf3828027 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.cpp +++ b/src/Mod/PartDesign/App/FeatureGroove.cpp @@ -34,6 +34,8 @@ # include # include # include +# include +# include #endif #include @@ -196,4 +198,40 @@ App::DocumentObjectExecReturn *Groove::execute(void) } } +bool Groove::suggestReversed(void) const +{ + // suggest a value for Reversed flag so that material is removed from the support + try { + Part::Part2DObject* sketch = getVerifiedSketch(); + std::vector wires = getSketchWires(); + TopoDS_Shape sketchshape = makeFace(wires); + + Base::Vector3f b = Base.getValue(); + Base::Vector3f v = Axis.getValue(); + + // get centre of gravity of the sketch face + GProp_GProps props; + BRepGProp::SurfaceProperties(sketchshape, props); + gp_Pnt cog = props.CentreOfMass(); + Base::Vector3f p_cog(cog.X(), cog.Y(), cog.Z()); + // get direction to cog from its projection on the revolve axis + Base::Vector3f perp_dir = p_cog - p_cog.Perpendicular(b, v); + // get cross product of projection direction with revolve axis direction + Base::Vector3f cross = v % perp_dir; + // get sketch vector pointing away from support material + Base::Placement SketchPos = sketch->Placement.getValue(); + Base::Rotation SketchOrientation = SketchPos.getRotation(); + Base::Vector3d SketchNormal(0,0,1); + SketchOrientation.multVec(SketchNormal,SketchNormal); + // simply convert double to float + Base::Vector3f norm(SketchNormal.x, SketchNormal.y, SketchNormal.z); + + // return true if the angle between norm and cross is acute + return norm * cross > 0.f; + } + catch (...) { + return false; + } +} + } diff --git a/src/Mod/PartDesign/App/FeatureGroove.h b/src/Mod/PartDesign/App/FeatureGroove.h index 7e637e607f..8fb2f2d994 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.h +++ b/src/Mod/PartDesign/App/FeatureGroove.h @@ -62,6 +62,8 @@ public: return "PartDesignGui::ViewProviderGroove"; } //@} + + bool suggestReversed(void) const; }; } //namespace PartDesign From 046ef46d147bbd709ee5934570e965141e836057 Mon Sep 17 00:00:00 2001 From: logari81 Date: Thu, 14 Feb 2013 00:39:10 +0100 Subject: [PATCH 7/8] PartDesign: Add method suggesting Revolution Reversed property so that material is always added to the support --- src/Mod/PartDesign/App/FeatureRevolution.cpp | 42 +++++++++++++++++++- src/Mod/PartDesign/App/FeatureRevolution.h | 2 + 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 84d0eba8eb..6745da5f40 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -34,6 +34,8 @@ # include # include # include +# include +# include #endif #include @@ -75,9 +77,9 @@ App::DocumentObjectExecReturn *Revolution::execute(void) // Validate parameters double angle = Angle.getValue(); if (angle < Precision::Confusion()) - return new App::DocumentObjectExecReturn("Angle of groove too small"); + return new App::DocumentObjectExecReturn("Angle of revolution too small"); if (angle > 360.0) - return new App::DocumentObjectExecReturn("Angle of groove too large"); + return new App::DocumentObjectExecReturn("Angle of revolution too large"); angle = Base::toRadians(angle); // Reverse angle if selected @@ -204,5 +206,41 @@ App::DocumentObjectExecReturn *Revolution::execute(void) return new App::DocumentObjectExecReturn(e.what()); } } + +bool Revolution::suggestReversed(void) const +{ + // suggest a value for Reversed flag so that material is added to the support + try { + Part::Part2DObject* sketch = getVerifiedSketch(); + std::vector wires = getSketchWires(); + TopoDS_Shape sketchshape = makeFace(wires); + + Base::Vector3f b = Base.getValue(); + Base::Vector3f v = Axis.getValue(); + + // get centre of gravity of the sketch face + GProp_GProps props; + BRepGProp::SurfaceProperties(sketchshape, props); + gp_Pnt cog = props.CentreOfMass(); + Base::Vector3f p_cog(cog.X(), cog.Y(), cog.Z()); + // get direction to cog from its projection on the revolve axis + Base::Vector3f perp_dir = p_cog - p_cog.Perpendicular(b, v); + // get cross product of projection direction with revolve axis direction + Base::Vector3f cross = v % perp_dir; + // get sketch vector pointing away from support material + Base::Placement SketchPos = sketch->Placement.getValue(); + Base::Rotation SketchOrientation = SketchPos.getRotation(); + Base::Vector3d SketchNormal(0,0,1); + SketchOrientation.multVec(SketchNormal,SketchNormal); + // simply convert double to float + Base::Vector3f norm(SketchNormal.x, SketchNormal.y, SketchNormal.z); + + // return true if the angle between norm and cross is acute + return norm * cross < 0.f; + } + catch (...) { + return false; + } +} } diff --git a/src/Mod/PartDesign/App/FeatureRevolution.h b/src/Mod/PartDesign/App/FeatureRevolution.h index 485c851f6e..89a79b5a3e 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.h +++ b/src/Mod/PartDesign/App/FeatureRevolution.h @@ -62,6 +62,8 @@ public: return "PartDesignGui::ViewProviderRevolution"; } //@} + + bool suggestReversed(void) const; }; } //namespace PartDesign From 68411f28d343a9b899ad04b09d5c6183a148427f Mon Sep 17 00:00:00 2001 From: logari81 Date: Thu, 14 Feb 2013 16:06:23 +0100 Subject: [PATCH 8/8] PartDesign: Intelligent defaults for the Reversed flag of Revolution/Groove features --- src/Mod/PartDesign/App/FeatureGroove.cpp | 79 +++++++++-------- src/Mod/PartDesign/App/FeatureGroove.h | 6 +- src/Mod/PartDesign/App/FeatureRevolution.cpp | 85 ++++++++++--------- src/Mod/PartDesign/App/FeatureRevolution.h | 6 +- src/Mod/PartDesign/Gui/Command.cpp | 10 ++- .../PartDesign/Gui/TaskGrooveParameters.cpp | 16 ++++ .../Gui/TaskRevolutionParameters.cpp | 16 ++++ 7 files changed, 135 insertions(+), 83 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureGroove.cpp b/src/Mod/PartDesign/App/FeatureGroove.cpp index 3cf3828027..ea2d5391b9 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.cpp +++ b/src/Mod/PartDesign/App/FeatureGroove.cpp @@ -85,49 +85,17 @@ App::DocumentObjectExecReturn *Groove::execute(void) if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); - Part::Part2DObject* sketch = 0; std::vector wires; TopoDS_Shape support; try { - sketch = getVerifiedSketch(); wires = getSketchWires(); support = getSupportShape(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); } - // get the Sketch plane - Base::Placement SketchPlm = sketch->Placement.getValue(); - - // get reference axis - App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); - const std::vector &subReferenceAxis = ReferenceAxis.getSubValues(); - if (pcReferenceAxis && pcReferenceAxis == sketch) { - bool hasValidAxis=false; - Base::Axis axis; - if (subReferenceAxis[0] == "V_Axis") { - hasValidAxis = true; - axis = sketch->getAxis(Part::Part2DObject::V_Axis); - } - else if (subReferenceAxis[0] == "H_Axis") { - hasValidAxis = true; - axis = sketch->getAxis(Part::Part2DObject::H_Axis); - } - else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { - int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); - if (AxId >= 0 && AxId < sketch->getAxisCount()) { - hasValidAxis = true; - axis = sketch->getAxis(AxId); - } - } - if (hasValidAxis) { - axis *= SketchPlm; - Base::Vector3d base=axis.getBase(); - Base::Vector3d dir=axis.getDirection(); - Base.setValue(base.x,base.y,base.z); - Axis.setValue(dir.x,dir.y,dir.z); - } - } + // update Axis from ReferenceAxis + updateAxis(); // get revolve axis Base::Vector3f b = Base.getValue(); @@ -198,10 +166,11 @@ App::DocumentObjectExecReturn *Groove::execute(void) } } -bool Groove::suggestReversed(void) const +bool Groove::suggestReversed(void) { - // suggest a value for Reversed flag so that material is removed from the support try { + updateAxis(); + Part::Part2DObject* sketch = getVerifiedSketch(); std::vector wires = getSketchWires(); TopoDS_Shape sketchshape = makeFace(wires); @@ -230,7 +199,43 @@ bool Groove::suggestReversed(void) const return norm * cross > 0.f; } catch (...) { - return false; + return Reversed.getValue(); + } +} + +void Groove::updateAxis(void) +{ + Part::Part2DObject* sketch = getVerifiedSketch(); + Base::Placement SketchPlm = sketch->Placement.getValue(); + + // get reference axis + App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); + const std::vector &subReferenceAxis = ReferenceAxis.getSubValues(); + if (pcReferenceAxis && pcReferenceAxis == sketch) { + bool hasValidAxis=false; + Base::Axis axis; + if (subReferenceAxis[0] == "V_Axis") { + hasValidAxis = true; + axis = sketch->getAxis(Part::Part2DObject::V_Axis); + } + else if (subReferenceAxis[0] == "H_Axis") { + hasValidAxis = true; + axis = sketch->getAxis(Part::Part2DObject::H_Axis); + } + else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { + int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); + if (AxId >= 0 && AxId < sketch->getAxisCount()) { + hasValidAxis = true; + axis = sketch->getAxis(AxId); + } + } + if (hasValidAxis) { + axis *= SketchPlm; + Base::Vector3d base=axis.getBase(); + Base::Vector3d dir=axis.getDirection(); + Base.setValue(base.x,base.y,base.z); + Axis.setValue(dir.x,dir.y,dir.z); + } } } diff --git a/src/Mod/PartDesign/App/FeatureGroove.h b/src/Mod/PartDesign/App/FeatureGroove.h index 8fb2f2d994..03616a0ff6 100644 --- a/src/Mod/PartDesign/App/FeatureGroove.h +++ b/src/Mod/PartDesign/App/FeatureGroove.h @@ -63,7 +63,11 @@ public: } //@} - bool suggestReversed(void) const; + /// suggests a value for Reversed flag so that material is always removed from the support + bool suggestReversed(void); +protected: + /// updates Axis from ReferenceAxis + void updateAxis(void); }; } //namespace PartDesign diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 6745da5f40..790f21cf81 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -43,7 +43,6 @@ #include #include "FeatureRevolution.h" -#include using namespace PartDesign; @@ -86,10 +85,8 @@ App::DocumentObjectExecReturn *Revolution::execute(void) if (Reversed.getValue() && !Midplane.getValue()) angle *= (-1.0); - Part::Part2DObject* sketch = 0; std::vector wires; try { - sketch = getVerifiedSketch(); wires = getSketchWires(); } catch (const Base::Exception& e) { return new App::DocumentObjectExecReturn(e.what()); @@ -103,41 +100,8 @@ App::DocumentObjectExecReturn *Revolution::execute(void) support = TopoDS_Shape(); } - // get the Sketch plane - Base::Placement SketchPlm = sketch->Placement.getValue(); - - // get reference axis - App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); - const std::vector &subReferenceAxis = ReferenceAxis.getSubValues(); - bool hasValidAxis=false; - if (pcReferenceAxis && pcReferenceAxis == sketch) { - Base::Axis axis; - if (subReferenceAxis[0] == "V_Axis") { - hasValidAxis = true; - axis = sketch->getAxis(Part::Part2DObject::V_Axis); - } - else if (subReferenceAxis[0] == "H_Axis") { - hasValidAxis = true; - axis = sketch->getAxis(Part::Part2DObject::H_Axis); - } - else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { - int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); - if (AxId >= 0 && AxId < sketch->getAxisCount()) { - hasValidAxis = true; - axis = sketch->getAxis(AxId); - } - } - if (hasValidAxis) { - axis *= SketchPlm; - Base::Vector3d base=axis.getBase(); - Base::Vector3d dir=axis.getDirection(); - Base.setValue(base.x,base.y,base.z); - Axis.setValue(dir.x,dir.y,dir.z); - } - } - if (!hasValidAxis) { - return new App::DocumentObjectExecReturn("No valid reference axis defined"); - } + // update Axis from ReferenceAxis + updateAxis(); // get revolve axis Base::Vector3f b = Base.getValue(); @@ -207,10 +171,11 @@ App::DocumentObjectExecReturn *Revolution::execute(void) } } -bool Revolution::suggestReversed(void) const +bool Revolution::suggestReversed(void) { - // suggest a value for Reversed flag so that material is added to the support try { + updateAxis(); + Part::Part2DObject* sketch = getVerifiedSketch(); std::vector wires = getSketchWires(); TopoDS_Shape sketchshape = makeFace(wires); @@ -235,11 +200,47 @@ bool Revolution::suggestReversed(void) const // simply convert double to float Base::Vector3f norm(SketchNormal.x, SketchNormal.y, SketchNormal.z); - // return true if the angle between norm and cross is acute + // return true if the angle between norm and cross is obtuse return norm * cross < 0.f; } catch (...) { - return false; + return Reversed.getValue(); + } +} + +void Revolution::updateAxis(void) +{ + Part::Part2DObject* sketch = getVerifiedSketch(); + Base::Placement SketchPlm = sketch->Placement.getValue(); + + // get reference axis + App::DocumentObject *pcReferenceAxis = ReferenceAxis.getValue(); + const std::vector &subReferenceAxis = ReferenceAxis.getSubValues(); + if (pcReferenceAxis && pcReferenceAxis == sketch) { + bool hasValidAxis=false; + Base::Axis axis; + if (subReferenceAxis[0] == "V_Axis") { + hasValidAxis = true; + axis = sketch->getAxis(Part::Part2DObject::V_Axis); + } + else if (subReferenceAxis[0] == "H_Axis") { + hasValidAxis = true; + axis = sketch->getAxis(Part::Part2DObject::H_Axis); + } + else if (subReferenceAxis[0].size() > 4 && subReferenceAxis[0].substr(0,4) == "Axis") { + int AxId = std::atoi(subReferenceAxis[0].substr(4,4000).c_str()); + if (AxId >= 0 && AxId < sketch->getAxisCount()) { + hasValidAxis = true; + axis = sketch->getAxis(AxId); + } + } + if (hasValidAxis) { + axis *= SketchPlm; + Base::Vector3d base=axis.getBase(); + Base::Vector3d dir=axis.getDirection(); + Base.setValue(base.x,base.y,base.z); + Axis.setValue(dir.x,dir.y,dir.z); + } } } diff --git a/src/Mod/PartDesign/App/FeatureRevolution.h b/src/Mod/PartDesign/App/FeatureRevolution.h index 89a79b5a3e..14e0c9a0a6 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.h +++ b/src/Mod/PartDesign/App/FeatureRevolution.h @@ -63,7 +63,11 @@ public: } //@} - bool suggestReversed(void) const; + /// suggests a value for Reversed flag so that material is always added to the support + bool suggestReversed(void); +protected: + /// updates Axis from ReferenceAxis + void updateAxis(void); }; } //namespace PartDesign diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp index 975412ab9d..67959a7411 100644 --- a/src/Mod/PartDesign/Gui/Command.cpp +++ b/src/Mod/PartDesign/Gui/Command.cpp @@ -48,8 +48,8 @@ #include #include -#include -#include +#include +#include using namespace std; @@ -343,6 +343,9 @@ void CmdPartDesignRevolution::activated(int iMsg) doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])", FeatName.c_str(), sketch->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.Angle = 360.0",FeatName.c_str()); + PartDesign::Revolution* pcRevolution = static_cast(getDocument()->getObject(FeatName.c_str())); + if (pcRevolution && pcRevolution->suggestReversed()) + doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str()); updateActive(); if (isActiveObjectValid()) { doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",sketch->getNameInDocument()); @@ -413,6 +416,9 @@ void CmdPartDesignGroove::activated(int iMsg) doCommand(Doc,"App.activeDocument().%s.ReferenceAxis = (App.activeDocument().%s,['V_Axis'])", FeatName.c_str(), sketch->getNameInDocument()); doCommand(Doc,"App.activeDocument().%s.Angle = 360.0",FeatName.c_str()); + PartDesign::Groove* pcGroove = static_cast(getDocument()->getObject(FeatName.c_str())); + if (pcGroove && pcGroove->suggestReversed()) + doCommand(Doc,"App.activeDocument().%s.Reversed = 1",FeatName.c_str()); updateActive(); if (isActiveObjectValid()) { doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",sketch->getNameInDocument()); diff --git a/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp b/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp index 8ec5940374..8e3c1add22 100644 --- a/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp @@ -134,6 +134,9 @@ void TaskGrooveParameters::onAxisChanged(int num) PartDesign::Groove* pcGroove = static_cast(GrooveView->getObject()); Sketcher::SketchObject *pcSketch = static_cast(pcGroove->Sketch.getValue()); if (pcSketch) { + App::DocumentObject *oldRefAxis = pcGroove->ReferenceAxis.getValue(); + std::vector oldSubRefAxis = pcGroove->ReferenceAxis.getSubValues(); + int maxcount = pcSketch->getAxisCount()+2; if (num == 0) pcGroove->ReferenceAxis.setValue(pcSketch, std::vector(1,"V_Axis")); @@ -146,6 +149,19 @@ void TaskGrooveParameters::onAxisChanged(int num) } if (num < maxcount && ui->axis->count() > maxcount) ui->axis->setMaxCount(maxcount); + + const std::vector &newSubRefAxis = pcGroove->ReferenceAxis.getSubValues(); + if (oldRefAxis != pcSketch || + oldSubRefAxis.size() != newSubRefAxis.size() || + oldSubRefAxis[0] != newSubRefAxis[0]) { + bool reversed = pcGroove->suggestReversed(); + if (reversed != pcGroove->Reversed.getValue()) { + pcGroove->Reversed.setValue(reversed); + ui->checkBoxReversed->blockSignals(true); + ui->checkBoxReversed->setChecked(reversed); + ui->checkBoxReversed->blockSignals(false); + } + } } if (updateView()) pcGroove->getDocument()->recomputeFeature(pcGroove); diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp index c5e6f75b92..abbf000c48 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp @@ -134,6 +134,9 @@ void TaskRevolutionParameters::onAxisChanged(int num) PartDesign::Revolution* pcRevolution = static_cast(RevolutionView->getObject()); Sketcher::SketchObject *pcSketch = static_cast(pcRevolution->Sketch.getValue()); if (pcSketch) { + App::DocumentObject *oldRefAxis = pcRevolution->ReferenceAxis.getValue(); + std::vector oldSubRefAxis = pcRevolution->ReferenceAxis.getSubValues(); + int maxcount = pcSketch->getAxisCount()+2; if (num == 0) pcRevolution->ReferenceAxis.setValue(pcSketch, std::vector(1,"V_Axis")); @@ -146,6 +149,19 @@ void TaskRevolutionParameters::onAxisChanged(int num) } if (num < maxcount && ui->axis->count() > maxcount) ui->axis->setMaxCount(maxcount); + + const std::vector &newSubRefAxis = pcRevolution->ReferenceAxis.getSubValues(); + if (oldRefAxis != pcSketch || + oldSubRefAxis.size() != newSubRefAxis.size() || + oldSubRefAxis[0] != newSubRefAxis[0]) { + bool reversed = pcRevolution->suggestReversed(); + if (reversed != pcRevolution->Reversed.getValue()) { + pcRevolution->Reversed.setValue(reversed); + ui->checkBoxReversed->blockSignals(true); + ui->checkBoxReversed->setChecked(reversed); + ui->checkBoxReversed->blockSignals(false); + } + } } if (updateView()) pcRevolution->getDocument()->recomputeFeature(pcRevolution);