diff --git a/Fltk/classificationEditor.cpp b/Fltk/classificationEditor.cpp index edaeb678221b4b49cf7f545bbae57fd6feac8814..2665eee9ae433dee98d1c2908f234ef0e4c5cf51 100644 --- a/Fltk/classificationEditor.cpp +++ b/Fltk/classificationEditor.cpp @@ -16,49 +16,10 @@ #include "GmshMessage.h" #include "MLine.h" #include "meshGFaceDelaunayInsertion.h" -#include "meshGFaceOptimize.h" #include "discreteEdge.h" #include "discreteFace.h" -edge_angle::edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2) - : v1(_v1), v2(_v2) -{ - if(!t2) angle = 0; - else{ - double c1[3]; - double c2[3]; - double c3[3]; - { - MVertex *p1 = t1->getVertex(0); - MVertex *p2 = t1->getVertex(1); - MVertex *p3 = t1->getVertex(2); - double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()}; - double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()}; - c1[2] = a[0] * b[1] - a[1] * b[0]; - c1[1] = -a[0] * b[2] + a[2] * b[0]; - c1[0] = a[1] * b[2] - a[2] * b[1]; - } - { - MVertex *p1 = t2->getVertex(0); - MVertex *p2 = t2->getVertex(1); - MVertex *p3 = t2->getVertex(2); - double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()}; - double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()}; - c2[2] = a[0] * b[1] - a[1] * b[0]; - c2[1] = -a[0] * b[2] + a[2] * b[0]; - c2[0] = a[1] * b[2] - a[2] * b[1]; - } - norme(c1); - norme(c2); - prodve(c1, c2, c3); - double cosa; prosca(c1, c2, &cosa); - double sina = norme(c3); - angle = atan2(sina, cosa); - } -} - -struct compareMLinePtr -{ +struct compareMLinePtr { bool operator () (MLine *l1, MLine *l2) const { static Less_Edge le; @@ -66,23 +27,6 @@ struct compareMLinePtr } }; -static void buildListOfEdgeAngle(e2t_cont adj, std::vector<edge_angle> &edges_detected, - std::vector<edge_angle> &edges_lonly) -{ - e2t_cont::iterator it = adj.begin(); - for(; it != adj.end(); ++it){ - if(it->second.second) - edges_detected.push_back(edge_angle(it->first.getVertex(0), - it->first.getVertex(1), - it->second.first, it->second.second)); - else - edges_lonly.push_back(edge_angle(it->first.getVertex(0), - it->first.getVertex(1), - it->second.first, it->second.second)); - } - std::sort(edges_detected.begin(), edges_detected.end()); -} - static void recurClassify(MTri3 *t, GFace *gf, std::map<MLine*, GEdge*, compareMLinePtr> &lines, std::map<MTriangle*, GFace*> &reverse) @@ -105,7 +49,7 @@ static void recurClassify(MTri3 *t, GFace *gf, } static GEdge *getNewModelEdge(GFace *gf1, GFace *gf2, - std::map<std::pair<int, int>, GEdge* > &newEdges) + std::map<std::pair<int, int>, GEdge*> &newEdges) { int t1 = gf1 ? gf1->tag() : -1; int t2 = gf2 ? gf2->tag() : -1; diff --git a/Fltk/classificationEditor.h b/Fltk/classificationEditor.h index b7153dded18f4b6a460d3738a0db8b2bbe2f4a28..b226b14d720dccd2ae4f5df27230970e17312e6e 100644 --- a/Fltk/classificationEditor.h +++ b/Fltk/classificationEditor.h @@ -13,6 +13,7 @@ #include <FL/Fl_Value_Input.H> #include "GModel.h" #include "MElement.h" +#include "meshGFaceOptimize.h" #define CLASS_BUTTON_SELECT_ELEMENTS 0 #define CLASS_BUTTON_SELECT_ALL_ELEMENTS 1 @@ -28,17 +29,6 @@ #define CLASS_VALUE_ANGLE 0 -class edge_angle { - public : - MVertex *v1, *v2; - double angle; - edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2); - bool operator < (const edge_angle &other) const - { - return other.angle < angle; - } -}; - class classificationEditor { public: std::vector<MTriangle*> elements; diff --git a/Mesh/meshGFaceOptimize.cpp b/Mesh/meshGFaceOptimize.cpp index 0cefd31171b45f0409d1cd31ad23557046fc9b4f..319d09c79817060af4d2f34f5e8e7067de604b2f 100644 --- a/Mesh/meshGFaceOptimize.cpp +++ b/Mesh/meshGFaceOptimize.cpp @@ -16,6 +16,43 @@ #include "GmshMessage.h" #include "Generator.h" +edge_angle::edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2) + : v1(_v1), v2(_v2) +{ + if(!t2) angle = 0; + else{ + double c1[3]; + double c2[3]; + double c3[3]; + { + MVertex *p1 = t1->getVertex(0); + MVertex *p2 = t1->getVertex(1); + MVertex *p3 = t1->getVertex(2); + double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()}; + double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()}; + c1[2] = a[0] * b[1] - a[1] * b[0]; + c1[1] = -a[0] * b[2] + a[2] * b[0]; + c1[0] = a[1] * b[2] - a[2] * b[1]; + } + { + MVertex *p1 = t2->getVertex(0); + MVertex *p2 = t2->getVertex(1); + MVertex *p3 = t2->getVertex(2); + double a[3] = {p1->x() - p2->x(), p1->y() - p2->y(), p1->z() - p2->z()}; + double b[3] = {p1->x() - p3->x(), p1->y() - p3->y(), p1->z() - p3->z()}; + c2[2] = a[0] * b[1] - a[1] * b[0]; + c2[1] = -a[0] * b[2] + a[2] * b[0]; + c2[0] = a[1] * b[2] - a[2] * b[1]; + } + norme(c1); + norme(c2); + prodve(c1, c2, c3); + double cosa; prosca(c1, c2, &cosa); + double sina = norme(c3); + angle = atan2(sina, cosa); + } +} + static void setLcsInit(MTriangle *t, std::map<MVertex*, double> &vSizes) { for(int i = 0; i < 3; i++){ @@ -194,6 +231,23 @@ void buildEdgeToTriangle(std::vector<MTriangle*> &tris, e2t_cont &adj) buildEdgeToElement(tris, adj); } +void buildListOfEdgeAngle(e2t_cont adj, std::vector<edge_angle> &edges_detected, + std::vector<edge_angle> &edges_lonly) +{ + e2t_cont::iterator it = adj.begin(); + for(; it != adj.end(); ++it){ + if(it->second.second) + edges_detected.push_back(edge_angle(it->first.getVertex(0), + it->first.getVertex(1), + it->second.first, it->second.second)); + else + edges_lonly.push_back(edge_angle(it->first.getVertex(0), + it->first.getVertex(1), + it->second.first, it->second.second)); + } + std::sort(edges_detected.begin(), edges_detected.end()); +} + void parametricCoordinates(MElement *t, GFace *gf, double u[4], double v[4]) { for(int j = 0; j < t->getNumVertices(); j++){ diff --git a/Mesh/meshGFaceOptimize.h b/Mesh/meshGFaceOptimize.h index 92e91df7be1fb5d88876a7f2816a8cba4818f139..e6b8e7538a5ee6a848da596ad29d24abc3688f92 100644 --- a/Mesh/meshGFaceOptimize.h +++ b/Mesh/meshGFaceOptimize.h @@ -16,11 +16,24 @@ class GFace; class MVertex; +class edge_angle { + public : + MVertex *v1, *v2; + double angle; + edge_angle(MVertex *_v1, MVertex *_v2, MElement *t1, MElement *t2); + bool operator < (const edge_angle &other) const + { + return other.angle < angle; + } +}; + typedef std::map<MVertex*, std::vector<MElement*> > v2t_cont; typedef std::map<MEdge, std::pair<MElement*, MElement*>, Less_Edge> e2t_cont; void buildVertexToTriangle(std::vector<MTriangle*> &, v2t_cont &adj); void buildEdgeToTriangle(std::vector<MTriangle*> &, e2t_cont &adj); +void buildListOfEdgeAngle(e2t_cont adj, std::vector<edge_angle> &edges_detected, + std::vector<edge_angle> &edges_lonly); void laplaceSmoothing(GFace *gf); void edgeSwappingLawson(GFace *gf); diff --git a/Plugin/CMakeLists.txt b/Plugin/CMakeLists.txt index 12b32aa25e5ffb3566f0101f8c89447d46ad19b8..55637ba2fb456ef4e06a34c45ca07810fe5b45a0 100644 --- a/Plugin/CMakeLists.txt +++ b/Plugin/CMakeLists.txt @@ -23,7 +23,7 @@ set(SRC Probe.cpp HarmonicToTime.cpp ModulusPhase.cpp HomologyComputation.cpp - Distance.cpp + Distance.cpp ExtractEdges.cpp ) file(GLOB HDR RELATIVE ${CMAKE_SOURCE_DIR}/Plugin *.h) diff --git a/Plugin/ExtractEdges.cpp b/Plugin/ExtractEdges.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f3fade5443ed4ee06d581438021a7e405b4bc9ca --- /dev/null +++ b/Plugin/ExtractEdges.cpp @@ -0,0 +1,91 @@ +// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to <gmsh@geuz.org>. + +#include "GModel.h" +#include "meshGFaceOptimize.h" +#include "ExtractEdges.h" + +StringXNumber ExtractEdgesOptions_Number[] = { + {GMSH_FULLRC, "Angle", NULL, 40.}, + {GMSH_FULLRC, "IncludeBoundary", NULL, 1.}, +}; + +extern "C" +{ + GMSH_Plugin *GMSH_RegisterExtractEdgesPlugin() + { + return new GMSH_ExtractEdgesPlugin(); + } +} + +std::string GMSH_ExtractEdgesPlugin::getHelp() const +{ + return "Plugin(ExtractEdges) extracts sharp edges " + "from a triangular mesh.\n\n" + "Plugin(ExtractEdges) creates one new view."; +} + +int GMSH_ExtractEdgesPlugin::getNbOptions() const +{ + return sizeof(ExtractEdgesOptions_Number) / sizeof(StringXNumber); +} + +StringXNumber *GMSH_ExtractEdgesPlugin::getOption(int iopt) +{ + return &ExtractEdgesOptions_Number[iopt]; +} + +static void add_edge(edge_angle &ea, PViewDataList *data) +{ + data->SL.push_back(ea.v1->x()); + data->SL.push_back(ea.v2->x()); + data->SL.push_back(ea.v1->y()); + data->SL.push_back(ea.v2->y()); + data->SL.push_back(ea.v1->z()); + data->SL.push_back(ea.v2->z()); + data->SL.push_back(1.); + data->SL.push_back(1.); + data->NbSL++; +} + +PView *GMSH_ExtractEdgesPlugin::execute(PView *v) +{ + std::vector<MTriangle*> elements; + for(GModel::fiter it = GModel::current()->firstFace(); + it != GModel::current()->lastFace(); ++it) + elements.insert(elements.end(), (*it)->triangles.begin(), + (*it)->triangles.end()); + + if(elements.empty()){ + Msg::Error("No triangles in mesh to extract edges from"); + return 0; + } + + PView *v2 = new PView(); + PViewDataList *data2 = getDataList(v2); + + e2t_cont adj; + buildEdgeToTriangle(elements, adj); + std::vector<edge_angle> edges_detected, edges_lonly; + buildListOfEdgeAngle(adj, edges_detected, edges_lonly); + + double threshold = ExtractEdgesOptions_Number[0].def / 180. * M_PI; + for(unsigned int i = 0; i < edges_detected.size(); i++){ + if(edges_detected[i].angle <= threshold) break; + add_edge(edges_detected[i], data2); + } + + if(ExtractEdgesOptions_Number[1].def){ + for(unsigned int i = 0; i < edges_lonly.size(); i++){ + add_edge(edges_lonly[i], data2); + } + } + + data2->setName("ExtractEdges"); + data2->setFileName("ExtractEdges.pos"); + data2->finalize(); + + return v2; +} diff --git a/Plugin/ExtractEdges.h b/Plugin/ExtractEdges.h new file mode 100644 index 0000000000000000000000000000000000000000..795ac0ed44304af5baa76311f603271226b72816 --- /dev/null +++ b/Plugin/ExtractEdges.h @@ -0,0 +1,31 @@ +// Gmsh - Copyright (C) 1997-2010 C. Geuzaine, J.-F. Remacle +// +// See the LICENSE.txt file for license information. Please report all +// bugs and problems to <gmsh@geuz.org>. + +#ifndef _EXTRACT_EDGES_H_ +#define _EXTRACT_EDGES_H_ + +#include "Plugin.h" + +extern "C" +{ + GMSH_Plugin *GMSH_RegisterExtractEdgesPlugin(); +} + +class GMSH_ExtractEdgesPlugin : public GMSH_PostPlugin +{ + public: + GMSH_ExtractEdgesPlugin(){} + std::string getName() const { return "ExtractEdges"; } + std::string getShortHelp() const + { + return "Extract sharp edges from triangular mesh"; + } + std::string getHelp() const; + int getNbOptions() const; + StringXNumber* getOption(int iopt); + PView *execute(PView *); +}; + +#endif diff --git a/Plugin/PluginManager.cpp b/Plugin/PluginManager.cpp index 2848acc40ad9907882fa2096ad1f20a139ae1320..592f1eb8ef8536364d93e8ebd72e5e1a2afb3bea 100644 --- a/Plugin/PluginManager.cpp +++ b/Plugin/PluginManager.cpp @@ -44,6 +44,7 @@ #include "GSHHS.h" #include "HomologyComputation.h" #include "Distance.h" +#include "ExtractEdges.h" // for testing purposes only :-) #undef HAVE_DLOPEN @@ -217,6 +218,8 @@ void PluginManager::registerDefaultPlugins() #endif allPlugins.insert(std::pair<std::string, GMSH_Plugin*> ("Distance", GMSH_RegisterDistancePlugin())); + allPlugins.insert(std::pair<std::string, GMSH_Plugin*> + ("ExtractEdges", GMSH_RegisterExtractEdgesPlugin())); } #if defined(HAVE_FLTK)