View Issue Details

IDProjectCategoryView StatusLast Update
0000689PartDesignFeaturepublic2012-05-07 07:44
Reporterhelo10 Assigned ToJriegel 
PrioritynormalSeverityminorReproducibilityhave not tried
Status closedResolutionfixed 
Summary0000689: create Chamfers/Fillets from Face
Descriptionmakes it possible to create chamfers and fillets from selected faces additional to edges.
TagsNo tags attached.
FreeCAD Information

Activities

2012-05-01 18:51

 

Chamfer_Fillet.patch (8,793 bytes)   
From 84c9a3e0b4f74053c6e4f9cb6ddb55cf56030a68 Mon Sep 17 00:00:00 2001
From: Jonathan Hahn <Jonathan.Hahn@t-online.de>
Date: Tue, 1 May 2012 09:27:15 +0200
Subject: [PATCH 1/2] allows faces as base for chamfers

---
 src/Mod/PartDesign/App/FeatureChamfer.cpp |   62 +++++++++++++++++++----------
 1 file changed, 42 insertions(+), 20 deletions(-)

diff --git a/src/Mod/PartDesign/App/FeatureChamfer.cpp b/src/Mod/PartDesign/App/FeatureChamfer.cpp
index e14406e..ce14019 100644
--- a/src/Mod/PartDesign/App/FeatureChamfer.cpp
+++ b/src/Mod/PartDesign/App/FeatureChamfer.cpp
@@ -27,7 +27,8 @@
 # include <TopExp.hxx>
 # include <TopExp_Explorer.hxx>
 # include <TopoDS.hxx>
-# include <TopoDS_Edge.hxx>
+# include <TopoDS_Edge.hxx>
+# include <TopoDS_Face.hxx>
 # include <TopTools_IndexedMapOfShape.hxx>
 # include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #endif
@@ -71,30 +72,51 @@ App::DocumentObjectExecReturn *Chamfer::execute(void)
     if (TopShape._Shape.IsNull())
         return new App::DocumentObjectExecReturn("Cannot chamfer invalid shape");
 
-    const std::vector<std::string>& SubVals = Base.getSubValuesStartsWith("Edge");
-    if (SubVals.size() == 0)
-        return new App::DocumentObjectExecReturn("No edges specified");
+    const std::vector<std::string>& SubVals = Base.getSubValuesStartsWith("Edge"),
+                                    FaceSubVals = Base.getSubValuesStartsWith("Face");
+
+    if(SubVals.size() == 0 && FaceSubVals.size() == 0)
+             return new App::DocumentObjectExecReturn("No edges specified");
 
     float size = Size.getValue();
 
-    this->positionByBase();
-    // create an untransformed copy of the base shape
-    Part::TopoShape baseShape(TopShape);
-    baseShape.setTransform(Base::Matrix4D());
-    try {
-        BRepFilletAPI_MakeChamfer mkChamfer(baseShape._Shape);
-
-        TopTools_IndexedMapOfShape mapOfEdges;
-        TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
-        TopExp::MapShapesAndAncestors(baseShape._Shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
-        TopExp::MapShapes(baseShape._Shape, TopAbs_EDGE, mapOfEdges);
+    this->positionByBase();
+
+    try {
+        // create an untransformed copy of the base shape
+        Part::TopoShape baseShape(TopShape);
+        baseShape.setTransform(Base::Matrix4D());
 
-        for (std::vector<std::string>::const_iterator it=SubVals.begin(); it != SubVals.end(); ++it) {
-            TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(it->c_str()));
-            const TopoDS_Face& face = TopoDS::Face(mapEdgeFace.FindFromKey(edge).First());
-            mkChamfer.Add(size, edge, face);
-        }
+        BRepFilletAPI_MakeChamfer mkChamfer(baseShape._Shape);
+
+        if (SubVals.size() > 0){
+            TopTools_IndexedMapOfShape mapOfEdges;
+            TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
+            TopExp::MapShapesAndAncestors(baseShape._Shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
+            TopExp::MapShapes(baseShape._Shape, TopAbs_EDGE, mapOfEdges);
+
+            for (std::vector<std::string>::const_iterator it=SubVals.begin(); it != SubVals.end(); ++it) {
+                TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(it->c_str()));
+                const TopoDS_Face& face = TopoDS::Face(mapEdgeFace.FindFromKey(edge).First());
+                mkChamfer.Add(size, edge, face);
+            }
+        }
+        if(FaceSubVals.size() > 0){
+
+            for (std::vector<std::string>::const_iterator it=FaceSubVals.begin(); it != FaceSubVals.end(); ++it) {
 
+                TopoDS_Face face = TopoDS::Face(baseShape.getSubShape(it->c_str()));
+
+                TopTools_IndexedMapOfShape mapOfEdges;
+                TopExp::MapShapes(face, TopAbs_EDGE, mapOfEdges);
+
+                for( int i = 1; i <= mapOfEdges.Extent(); ++i) {
+                    TopoDS_Edge edge = TopoDS::Edge(mapOfEdges.FindKey(i));
+                    mkChamfer.Add(size, edge , TopoDS::Face(baseShape.getSubShape(it->c_str())));
+                }
+            }
+        }
+
         mkChamfer.Build();
         if (!mkChamfer.IsDone())
             return new App::DocumentObjectExecReturn("Failed to create chamfer");
-- 
1.7.9.5


From 210adc9e85f2fd4847ab30c0c9f2979141e9c384 Mon Sep 17 00:00:00 2001
From: Jonathan Hahn <Jonathan.Hahn@t-online.de>
Date: Tue, 1 May 2012 22:22:31 +0200
Subject: [PATCH 2/2] adds fillets from faces

---
 src/Mod/PartDesign/App/FeatureChamfer.cpp |    7 ++--
 src/Mod/PartDesign/App/FeatureFillet.cpp  |   52 ++++++++++++++++++++++-------
 2 files changed, 44 insertions(+), 15 deletions(-)

diff --git a/src/Mod/PartDesign/App/FeatureChamfer.cpp b/src/Mod/PartDesign/App/FeatureChamfer.cpp
index ce14019..947a66b 100644
--- a/src/Mod/PartDesign/App/FeatureChamfer.cpp
+++ b/src/Mod/PartDesign/App/FeatureChamfer.cpp
@@ -82,10 +82,11 @@ App::DocumentObjectExecReturn *Chamfer::execute(void)
 
     this->positionByBase();
 
+    // create an untransformed copy of the base shape
+    Part::TopoShape baseShape(TopShape);
+    baseShape.setTransform(Base::Matrix4D());
+
     try {
-        // create an untransformed copy of the base shape
-        Part::TopoShape baseShape(TopShape);
-        baseShape.setTransform(Base::Matrix4D());
 
         BRepFilletAPI_MakeChamfer mkChamfer(baseShape._Shape);
 
diff --git a/src/Mod/PartDesign/App/FeatureFillet.cpp b/src/Mod/PartDesign/App/FeatureFillet.cpp
index 3b9470c..cab9911 100644
--- a/src/Mod/PartDesign/App/FeatureFillet.cpp
+++ b/src/Mod/PartDesign/App/FeatureFillet.cpp
@@ -23,10 +23,14 @@
 
 #include "PreCompiled.h"
 #ifndef _PreComp_
-# include <BRepFilletAPI_MakeFillet.hxx>
+# include <BRepFilletAPI_MakeFillet.hxx>
+# include <TopExp.hxx>
 # include <TopExp_Explorer.hxx>
 # include <TopoDS.hxx>
-# include <TopoDS_Edge.hxx>
+# include <TopoDS_Edge.hxx>
+# include <TopoDS_Face.hxx>
+# include <TopTools_IndexedMapOfShape.hxx>
+# include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
 #endif
 
 #include <Mod/Part/App/TopoShape.h>
@@ -68,29 +72,53 @@ App::DocumentObjectExecReturn *Fillet::execute(void)
     if (TopShape._Shape.IsNull())
         return new App::DocumentObjectExecReturn("Cannot fillet invalid shape");
 
-    const std::vector<std::string>& SubVals = Base.getSubValuesStartsWith("Edge");
-    if (SubVals.size() == 0)
-        return new App::DocumentObjectExecReturn("No edges specified");
+    const std::vector<std::string>& SubEdgeValues = Base.getSubValuesStartsWith("Edge"),
+                                     SubFaceValues = Base.getSubValuesStartsWith("Face");
+
+    if (SubEdgeValues.size() == 0 && SubFaceValues.size() == 0)
+        return new App::DocumentObjectExecReturn("No edges or faces specified");
 
     float radius = Radius.getValue();
 
-    this->positionByBase();
+    this->positionByBase();
+
     // create an untransformed copy of the base shape
     Part::TopoShape baseShape(TopShape);
-    baseShape.setTransform(Base::Matrix4D());
+    baseShape.setTransform(Base::Matrix4D());
+
     try {
         BRepFilletAPI_MakeFillet mkFillet(baseShape._Shape);
+
+        if(SubEdgeValues.size() > 0){
 
-        for (std::vector<std::string>::const_iterator it=SubVals.begin(); it != SubVals.end(); ++it) {
-            TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(it->c_str()));
-            mkFillet.Add(radius, edge);
+            for (std::vector<std::string>::const_iterator it=SubEdgeValues.begin(); it != SubEdgeValues.end(); ++it) {
+                TopoDS_Edge edge = TopoDS::Edge(baseShape.getSubShape(it->c_str()));
+                mkFillet.Add(radius, edge);
+            }
+        }
+
+        if(SubFaceValues.size() > 0){
+            for (std::vector<std::string>::const_iterator it=SubFaceValues.begin(); it != SubFaceValues.end(); ++it) {
+
+                TopoDS_Face face = TopoDS::Face(baseShape.getSubShape(it->c_str()));
+
+                TopTools_IndexedMapOfShape mapOfEdges;
+                TopExp::MapShapes(face, TopAbs_EDGE, mapOfEdges);
+
+                for( int i = 1; i <= mapOfEdges.Extent(); ++i) {
+                    TopoDS_Edge edge = TopoDS::Edge(mapOfEdges.FindKey(i));
+                    mkFillet.Add(radius, edge);
+                }
+            }
         }
 
-        mkFillet.Build();
+        mkFillet.Build();
+
         if (!mkFillet.IsDone())
             return new App::DocumentObjectExecReturn("Failed to create fillet");
 
-        TopoDS_Shape shape = mkFillet.Shape();
+        TopoDS_Shape shape = mkFillet.Shape();
+
         if (shape.IsNull())
             return new App::DocumentObjectExecReturn("Resulting shape is null");
 
-- 
1.7.9.5

Chamfer_Fillet.patch (8,793 bytes)   

helo10

2012-05-01 18:58

reporter   ~0001988

maybe more patch than feature..

2012-05-06 06:24

 

ChamferFilletfromFace.patch (9,220 bytes)   
From 51a71c5059e1ee17820a5f37648eebd68830d7d3 Mon Sep 17 00:00:00 2001
From: Jonathan Hahn <Jonathan.Hahn@t-online.de>
Date: Sun, 6 May 2012 10:20:48 +0200
Subject: [PATCH] adds edge filter to chamfer/fillet creation and replaces
 faces through their edges

---
 src/Mod/PartDesign/Gui/Command.cpp |  207 ++++++++++++++++++++++++++++++++++--
 1 file changed, 201 insertions(+), 6 deletions(-)

diff --git a/src/Mod/PartDesign/Gui/Command.cpp b/src/Mod/PartDesign/Gui/Command.cpp
index ddf3240..8657388 100644
--- a/src/Mod/PartDesign/Gui/Command.cpp
+++ b/src/Mod/PartDesign/Gui/Command.cpp
@@ -22,10 +22,22 @@
 
 
 #include "PreCompiled.h"
-#ifndef _PreComp_
+#ifndef _PreComp_
+# include <BRep_Tool.hxx>
 # include <TopExp_Explorer.hxx>
-# include <QMessageBox>
+# include <TopoDS.hxx>
+# include <TopoDS_Edge.hxx>
+# include <TopoDS_Shape.hxx>
+# include <TopoDS_Face.hxx>
+# include <TopExp.hxx>
+# include <TopTools_ListOfShape.hxx>
+# include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
+# include <TopTools_IndexedMapOfShape.hxx>
+# include <QMessageBox>
 #endif
+
+#include <sstream>
+#include <algorithm>
 
 #include <Gui/Application.h>
 #include <Gui/Command.h>
@@ -334,7 +346,7 @@ CmdPartDesignFillet::CmdPartDesignFillet()
 
 void CmdPartDesignFillet::activated(int iMsg)
 {
-    std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
+    std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx();
 
     if (selection.size() != 1) {
         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
@@ -344,10 +356,101 @@ void CmdPartDesignFillet::activated(int iMsg)
 
     if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){
         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"),
-            QObject::tr("Fillet works only on parts"));
+        QObject::tr("Fillet works only on parts"));
+        return;
+    }
+
+    Part::Feature *base = static_cast<Part::Feature*>(selection[0].getObject());
+
+    const Part::TopoShape& TopShape = base->Shape.getShape();
+    if (TopShape._Shape.IsNull()){
+        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+        QObject::tr("Shape of selected Part is empty"));
         return;
+    }
+
+    TopTools_IndexedMapOfShape mapOfEdges;
+    TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
+    TopExp::MapShapesAndAncestors(TopShape._Shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
+    TopExp::MapShapes(TopShape._Shape, TopAbs_EDGE, mapOfEdges);
+
+    std::vector<std::string> SubNames = std::vector<std::string>(selection[0].getSubNames());
+
+    int i = 0;
+
+    while( i < SubNames.size())
+    {
+        std::string aSubName = static_cast<std::string>(SubNames.at(i));
+
+        if (aSubName.size() > 4 && aSubName.substr(0,4) == "Edge") {
+            TopoDS_Edge edge = TopoDS::Edge(TopShape.getSubShape(aSubName.c_str()));
+            const TopTools_ListOfShape& los = mapEdgeFace.FindFromKey(edge);
+
+            if(los.Extent() != 2)
+            {
+                SubNames.erase(SubNames.begin()+i);
+                continue;
+            }
+
+            const TopoDS_Shape& face1 = los.First();
+            const TopoDS_Shape& face2 = los.Last();
+            GeomAbs_Shape cont = BRep_Tool::Continuity(TopoDS::Edge(edge),
+                                                       TopoDS::Face(face1),
+                                                       TopoDS::Face(face2));
+            if (cont != GeomAbs_C0) {
+                SubNames.erase(SubNames.begin()+i);
+                continue;
+            }
+
+            i++;
+        }
+        else if(aSubName.size() > 4 && aSubName.substr(0,4) == "Face") {
+            TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(aSubName.c_str()));
+
+            TopTools_IndexedMapOfShape mapOfFaces;
+            TopExp::MapShapes(face, TopAbs_EDGE, mapOfFaces);
+
+            for( int j = 1; j <= mapOfFaces.Extent(); ++j) {
+                TopoDS_Edge edge = TopoDS::Edge(mapOfFaces.FindKey(j));
+
+                int id = mapOfEdges.FindIndex(edge);
+
+                std::stringstream buf;
+                buf << "Edge";
+                buf << id;
+
+                if(std::find(SubNames.begin(),SubNames.end(),buf.str()) == SubNames.end())
+                {
+                    SubNames.push_back(buf.str());
+                }
+
+            }
+
+            SubNames.erase(SubNames.begin()+i);
+        }
+    }
+
+    if(SubNames.size() == 0){
+        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+        QObject::tr("No Fillet possilbe on seleced faces/edges"));
+        return;
+    }
+
+    std::string SelString;
+    SelString += "(App.";
+    SelString += "ActiveDocument";//getObject()->getDocument()->getName();
+    SelString += ".";
+    SelString += selection[0].getFeatName();
+    SelString += ",[";
+    for(std::vector<std::string>::const_iterator it = SubNames.begin();it!=SubNames.end();++it){
+        SelString += "\"";
+        SelString += *it;
+        SelString += "\"";
+        if(it != --SubNames.end())
+            SelString += ",";
     }
-    std::string SelString = selection[0].getAsPropertyLinkSubString();
+    SelString += "])";
+
     std::string FeatName = getUniqueObjectName("Fillet");
 
     openCommand("Make Fillet");
@@ -397,8 +500,100 @@ void CmdPartDesignChamfer::activated(int iMsg)
         QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"),
             QObject::tr("Chamfer works only on parts"));
         return;
+    }
+
+    Part::Feature *base = static_cast<Part::Feature*>(selection[0].getObject());
+
+    const Part::TopoShape& TopShape = base->Shape.getShape();
+
+    if (TopShape._Shape.IsNull()){
+        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+            QObject::tr("Shape of selected part is empty"));
+        return;
+    }
+
+    TopTools_IndexedMapOfShape mapOfEdges;
+    TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace;
+    TopExp::MapShapesAndAncestors(TopShape._Shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace);
+    TopExp::MapShapes(TopShape._Shape, TopAbs_EDGE, mapOfEdges);
+
+    std::vector<std::string> SubNames = std::vector<std::string>(selection[0].getSubNames());
+
+    int i = 0;
+
+    while( i < SubNames.size())
+    {
+        std::string aSubName = static_cast<std::string>(SubNames.at(i));
+
+        if (aSubName.size() > 4 && aSubName.substr(0,4) == "Edge") {
+            TopoDS_Edge edge = TopoDS::Edge(TopShape.getSubShape(aSubName.c_str()));
+            const TopTools_ListOfShape& los = mapEdgeFace.FindFromKey(edge);
+
+            if(los.Extent() != 2)
+            {
+                SubNames.erase(SubNames.begin()+i);
+                continue;
+            }
+
+            const TopoDS_Shape& face1 = los.First();
+            const TopoDS_Shape& face2 = los.Last();
+            GeomAbs_Shape cont = BRep_Tool::Continuity(TopoDS::Edge(edge),
+                                                       TopoDS::Face(face1),
+                                                       TopoDS::Face(face2));
+            if (cont != GeomAbs_C0) {
+                SubNames.erase(SubNames.begin()+i);
+                continue;
+            }
+
+            i++;
+        }
+        else if(aSubName.size() > 4 && aSubName.substr(0,4) == "Face") {
+            TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(aSubName.c_str()));
+
+            TopTools_IndexedMapOfShape mapOfFaces;
+            TopExp::MapShapes(face, TopAbs_EDGE, mapOfFaces);
+
+            for( int j = 1; j <= mapOfFaces.Extent(); ++j) {
+                TopoDS_Edge edge = TopoDS::Edge(mapOfFaces.FindKey(j));
+
+                int id = mapOfEdges.FindIndex(edge);
+
+                std::stringstream buf;
+                buf << "Edge";
+                buf << id;
+
+                if(std::find(SubNames.begin(),SubNames.end(),buf.str()) == SubNames.end())
+                {
+                    SubNames.push_back(buf.str());
+                }
+
+            }
+
+            SubNames.erase(SubNames.begin()+i);
+        }
+    }
+
+    if(SubNames.size() == 0){
+        QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"),
+        QObject::tr("No Fillet possilbe on seleced faces/edges"));
+        return;
+    }
+
+    std::string SelString;
+    SelString += "(App.";
+    SelString += "ActiveDocument";//getObject()->getDocument()->getName();
+    SelString += ".";
+    SelString += selection[0].getFeatName();
+    SelString += ",[";
+    for(std::vector<std::string>::const_iterator it = SubNames.begin();it!=SubNames.end();++it){
+        SelString += "\"";
+        SelString += *it;
+        SelString += "\"";
+        if(it != --SubNames.end())
+            SelString += ",";
     }
-    std::string SelString = selection[0].getAsPropertyLinkSubString();
+    SelString += "])";
+
     std::string FeatName = getUniqueObjectName("Chamfer");
 
     openCommand("Make Chamfer");
-- 
1.7.9.5

ChamferFilletfromFace.patch (9,220 bytes)   

helo10

2012-05-06 06:24

reporter   ~0002021

ignore Chamfer_Fillet.patch
ChamferFilletfromFace.patch replaces it

wmayer

2012-05-07 07:44

administrator   ~0002027

git show 3b2dc81

Issue History

Date Modified Username Field Change
2012-05-01 18:51 helo10 New Issue
2012-05-01 18:51 helo10 File Added: Chamfer_Fillet.patch
2012-05-01 18:58 helo10 Note Added: 0001988
2012-05-05 18:00 yorik Project FreeCAD => PartDesign
2012-05-06 06:24 helo10 File Added: ChamferFilletfromFace.patch
2012-05-06 06:24 helo10 Note Added: 0002021
2012-05-06 11:57 Jriegel Status new => assigned
2012-05-06 11:57 Jriegel Assigned To => Jriegel
2012-05-07 07:44 wmayer Note Added: 0002027
2012-05-07 07:44 wmayer Status assigned => closed
2012-05-07 07:44 wmayer Resolution open => fixed