1 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 // + This file is part of enGrid. +
5 // + Copyright 2008-2014 enGits GmbH +
7 // + enGrid is free software: you can redistribute it and/or modify +
8 // + it under the terms of the GNU General Public License as published by +
9 // + the Free Software Foundation, either version 3 of the License, or +
10 // + (at your option) any later version. +
12 // + enGrid is distributed in the hope that it will be useful, +
13 // + but WITHOUT ANY WARRANTY; without even the implied warranty of +
14 // + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +
15 // + GNU General Public License for more details. +
17 // + You should have received a copy of the GNU General Public License +
18 // + along with enGrid. If not, see <http://www.gnu.org/licenses/>. +
20 // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
22 #include "cgaltricadinterface.h"
23 #include "meshpartition.h"
25 CgalTriCadInterface::CgalTriCadInterface(vtkUnstructuredGrid
*grid
)
27 m_BGrid
= vtkUnstructuredGrid::New();
28 makeCopy(grid
, m_BGrid
);
29 m_BPart
.setGrid(m_BGrid
, true);
33 EG_STOPDATE("2014-08-01");
34 //getXmlSetting("engrid/surface/settings", "feature_angle", feature_angle);
35 getSet("surface meshing", "feature angle", 20, feature_angle
);
36 feature_angle
= GeometryTools::deg2rad(feature_angle
);
38 // build triangle tree
41 QVector
<vtkIdType
> tris
;
42 getAllCellsOfType(VTK_TRIANGLE
, tris
, m_BGrid
);
43 m_Triangles
.fill(Triangle(), tris
.size());
44 m_Tri2Grid
.fill(-1, tris
.size());
46 foreach (vtkIdType id_cell
, tris
) {
47 EG_GET_CELL(id_cell
, m_BGrid
);
49 m_BGrid
->GetPoint(pts
[0], a
.data());
50 m_BGrid
->GetPoint(pts
[1], b
.data());
51 m_BGrid
->GetPoint(pts
[2], c
.data());
52 m_Triangles
[i
] = Triangle(Point(a
[0], a
[1], a
[2]), Point(b
[0], b
[1], b
[2]), Point(c
[0], c
[1], c
[2]));
53 m_Tri2Grid
[i
] = id_cell
;
56 m_TriangleTree
.rebuild(m_Triangles
.begin(), m_Triangles
.end());
57 m_TriangleTree
.accelerate_distance_queries();
64 EG_VTKDCC(vtkIntArray
, cell_code
, m_BGrid
, "cell_code");
65 EG_FORALL_NODES(id_node1
, m_BGrid
) {
66 for (int i
= 0; i
< m_BPart
.n2nGSize(id_node1
); ++i
) {
67 vtkIdType id_node2
= m_BPart
.n2nGG(id_node1
, i
);
68 if (id_node1
< id_node2
) {
69 QVector
<vtkIdType
> id_face
;
70 m_BPart
.getEdgeFaces(id_node1
, id_node2
, id_face
);
71 if (id_face
.size() == 2) {
72 bool append_edge
= false;
73 if (cell_code
->GetValue(id_face
[0]) != cell_code
->GetValue(id_face
[1])) {
76 vec3_t n1
= GeometryTools::cellNormal(m_BGrid
, id_face
[0]);
77 vec3_t n2
= GeometryTools::cellNormal(m_BGrid
, id_face
[1]);
78 double alpha
= GeometryTools::angle(n1
, n2
);
79 if (alpha
>= feature_angle
) {
85 m_BGrid
->GetPoint(id_node1
, x1
.data());
86 m_BGrid
->GetPoint(id_node2
, x2
.data());
87 segs
.append(Segment(Point(x1
[0], x1
[1], x1
[2]), Point(x2
[0], x2
[1], x2
[2])));
93 m_Segments
.resize(segs
.size());
94 qCopy(segs
.begin(), segs
.end(), m_Segments
.begin());
95 m_SegmentTree
.rebuild(m_Segments
.begin(), m_Segments
.end());
96 m_SegmentTree
.accelerate_distance_queries();
99 setName("CgalTriCadInterface");
100 computeSurfaceCurvature();
101 //m_ShootRayImplemented = true;
104 void CgalTriCadInterface::computeSurfaceCurvature()
106 QVector
<double> node_radius(m_BGrid
->GetNumberOfPoints(), EG_LARGE_REAL
);
107 for (vtkIdType id_node
= 0; id_node
< m_BGrid
->GetNumberOfPoints(); ++id_node
) {
109 m_BGrid
->GetPoint(id_node
, x1
.data());
110 vec3_t n1
= m_BPart
.globalNormal(id_node
);
111 for (int i
= 0; i
< m_BPart
.n2nGSize(id_node
); ++i
) {
112 vtkIdType id_neigh
= m_BPart
.n2nGG(id_node
, i
);
113 vec3_t n2
= m_BPart
.globalNormal(id_neigh
);
114 double scal_prod
= max(-1.0, min(1.0, n1
*n2
));
115 double alpha
= max(1e-3, acos(scal_prod
));
118 m_BGrid
->GetPoint(id_neigh
, x2
.data());
119 double a
= (x1
- x2
).abs();
120 node_radius
[id_node
] = min(node_radius
[id_node
], a
/alpha
);
125 // compute weighted (distance) average of radii
126 QVector
<double> R_new(m_BGrid
->GetNumberOfPoints(), 1e99
);
127 for (vtkIdType id_node
= 0; id_node
< m_BGrid
->GetNumberOfPoints(); ++id_node
) {
129 m_BGrid
->GetPoint(id_node
, x1
.data());
130 int N
= m_BPart
.n2nGSize(id_node
);
131 QVector
<double> L(N
);
132 QVector
<double> R(N
, -1);
134 bool average
= false;
135 for (int i
= 0; i
< N
; ++i
) {
136 vtkIdType id_neigh
= m_BPart
.n2nGG(id_node
, i
);
138 m_BGrid
->GetPoint(id_neigh
, x2
.data());
139 L
[i
] = (x2
- x1
).abs();
140 if (node_radius
[id_neigh
] < 1e90
&& L
[i
] > 0) {
141 R
[i
] = node_radius
[id_neigh
];
142 Lmax
= max(Lmax
, L
[i
]);
148 double total_weight
= 0;
149 for (int i
= 0; i
< N
; ++i
) {
151 R_new
[id_node
] += Lmax
/L
[i
] * R
[i
];
152 total_weight
+= Lmax
/L
[i
];
153 //R_new[id_node] += R[i];
154 //total_weight += 1.0;
157 R_new
[id_node
] /= total_weight
;
162 m_Radius
.fill(0, m_BGrid
->GetNumberOfCells());
163 EG_FORALL_CELLS(id_cell
, m_BGrid
) {
164 EG_GET_CELL(id_cell
, m_BGrid
);
165 for (int i
= 0; i
< num_pts
; ++i
) {
166 m_Radius
[id_cell
] = max(m_Radius
[id_cell
], node_radius
[pts
[i
]]);
171 CgalTriCadInterface::Ray
CgalTriCadInterface::createRay(vec3_t x1
, vec3_t v
)
173 Point
p1(x1
[0], x1
[1], x1
[2]);
175 Point
p2(x2
[0], x2
[1], x2
[2]);
179 vec3_t
CgalTriCadInterface::snap(vec3_t x
, bool)
181 Point
p(x
[0], x
[1], x
[2]);
182 TrianglePointAndPrimitiveId result
= m_TriangleTree
.closest_point_and_primitive(p
);
183 Point cp
= result
.first
;
184 Triangle
* T
= result
.second
;
185 int id
= (T
- m_Triangles
.begin());
186 vtkIdType id_face
= m_Tri2Grid
[id
];
187 m_LastNormal
= GeometryTools::cellNormal(m_BGrid
, id_face
);
188 m_LastNormal
.normalise();
189 m_LastRadius
= m_Radius
[id_face
];
190 vec3_t x_snap
= vec3_t(cp
[0], cp
[1], cp
[2]);
194 vec3_t
CgalTriCadInterface::snapNode(vtkIdType id_node
, vec3_t x
, bool correct_curvature
)
196 vec3_t x_snap
= snap(x
, correct_curvature
);
197 vec3_t n_node
= m_FPart
.globalNormal(id_node
);
198 if (n_node
*m_LastNormal
< 0) {
199 double dist_min
= EG_LARGE_REAL
;
200 Ray ray
= createRay(x
, n_node
);
201 std::list
<Intersection
> intersections
;
202 m_TriangleTree
.all_intersections(ray
, std::back_inserter(intersections
));
203 for (std::list
<Intersection
>::iterator i
= intersections
.begin(); i
!= intersections
.end(); ++i
) {
204 int id
= (i
->second
- m_Triangles
.begin());
205 vtkIdType id_face
= m_Tri2Grid
[id
];
206 vec3_t n
= GeometryTools::cellNormal(m_BGrid
, id_face
);
209 if (i
->first
.type() == typeid(Point
)) {
210 Point p
= boost::get
<Point
>(i
->first
);
211 vec3_t
xs(p
[0], p
[1], p
[2]);
212 double dist
= (x
- xs
).abs();
213 if (dist
< dist_min
) {
217 m_LastRadius
= m_Radius
[id_face
];
226 vec3_t
CgalTriCadInterface::snapToEdge(vec3_t x
)
228 Point
p(x
[0], x
[1], x
[2]);
229 Point cp
= m_SegmentTree
.closest_point(p
);
230 vec3_t x_snap
= vec3_t(cp
[0], cp
[1], cp
[2]);
234 vec3_t
CgalTriCadInterface::snapToCorner(vec3_t
)
239 CgalTriCadInterface::HitType
CgalTriCadInterface::shootRay(vec3_t x
, vec3_t v
, vec3_t
&x_hit
, vec3_t
&n_hit
, double &r
)
244 void CgalTriCadInterface::computeIntersections(vec3_t x
, vec3_t v
, QVector
<QPair
<vec3_t
, vtkIdType
> > &intersections
)
246 Ray ray
= createRay(x
, v
);
247 std::list
<Intersection
> inters
;
248 m_TriangleTree
.all_intersections(ray
, std::back_inserter(inters
));
249 intersections
.resize(inters
.size());
250 int i_intersections
= 0;
251 for (std::list
<Intersection
>::iterator i
= inters
.begin(); i
!= inters
.end(); ++i
) {
252 int id
= (i
->second
- m_Triangles
.begin());
253 if (i
->first
.type() == typeid(Point
)) {
254 intersections
[i_intersections
].second
= m_Tri2Grid
[id
];
255 Point p
= boost::get
<Point
>(i
->first
);
256 vec3_t
xs(p
[0], p
[1], p
[2]);
257 intersections
[i_intersections
].first
= xs
;