Line data Source code
1 : /*
2 : * Copyright (c) 2007-2015: Sebastian Reiter
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #include <iostream>
34 : #include "traverser_project_point.h"
35 : #include "../node_tree.h"
36 : #include "common/log.h"
37 : #include "common/profiler/profiler.h"
38 :
39 : using namespace std;
40 :
41 : namespace ug{
42 : namespace node_tree
43 : {
44 :
45 : /*
46 : force_find muss überarbeitet werden:
47 : Problem: kleinste box in der der knoten liegt hält keine dreiecke.
48 : Ansatz: Falls nach dem Abarbeiten der nächst kleineren Box der Status
49 : noch auf SEARCHING steht, wird er auf FORCE_FIND gesetzt.
50 : War der Status auf SEARCHING, wurde aber von Kindknoten oder dem
51 : Knoten selbst auf FORCE_FIND gesetzt, so wird über alle Nachbarn
52 : der Box iteriert und mit ihnen ein Test durchgeführt.
53 : Ist der Status zu Begin der Evaluierung eines Knotens auf FORCE_FIND,
54 : so werden gleich alle Kind-Knoten evaluiert.
55 : */
56 :
57 0 : Traverser_ProjectPoint::Traverser_ProjectPoint()
58 : {
59 0 : m_closestElemID = -1;
60 0 : m_closestElemType = 0;
61 0 : }
62 :
63 0 : Traverser_ProjectPoint::~Traverser_ProjectPoint()
64 : {
65 0 : }
66 :
67 0 : bool Traverser_ProjectPoint::
68 : project(const vector3& point, SPNode nodeGraph,
69 : vector3* pPointNormal)
70 : {
71 0 : m_searchState = SEARCHING;
72 0 : m_distance = -1.0;
73 0 : m_closestElemID = -1;
74 0 : m_closestElemType = 0;
75 : m_point = point;
76 :
77 0 : if(pPointNormal){
78 0 : m_checkNormals = true;
79 : m_pointNormal = *pPointNormal;
80 : }
81 : else
82 0 : m_checkNormals= false;
83 :
84 0 : Traverser_CollisionTree::apply(nodeGraph);
85 :
86 0 : return m_searchState == GOT_ONE;
87 : }
88 :
89 0 : CollisionElementID Traverser_ProjectPoint::
90 : get_closest_element_id()
91 : {
92 0 : return m_closestElemID;
93 : }
94 :
95 0 : void Traverser_ProjectPoint::handle_group(GroupNode* group)
96 : {
97 0 : SearchState tSearchState = m_searchState;
98 0 : switch(tSearchState)
99 : {
100 0 : case SEARCHING:
101 : {
102 : // traverse each subnode
103 0 : int numChildren = group->num_children();
104 :
105 0 : for(int i = 0; i < numChildren; ++i)
106 : {
107 0 : traverse_object(group->get_child(i).get());
108 :
109 : // check whether the state changed during traversal of
110 : // the i-th subnode
111 0 : if(m_searchState != SEARCHING){
112 : // the state changed. we have to traverse the neighbours
113 : // of this node again, since other boxed-groups may be
114 : // entered now.
115 : // ignore child i (since this has been checked already)
116 0 : for(int j = 0; j < numChildren; ++j)
117 : {
118 0 : if(j != i)
119 0 : traverse_object(group->get_child(j).get());
120 : }
121 : // all children have been traversed. We're done in here.
122 : break;
123 : }
124 : }
125 :
126 : // At this point we have traversed all child nodes of
127 : // the node. If we're still in SEARCHING mode at this
128 : // point, we have to force a find and re-traverse the
129 : // children.
130 0 : if(m_searchState == SEARCHING){
131 0 : m_searchState = FORCE_FIND;
132 0 : Traverser_CollisionTree::handle_group(group);
133 : }
134 : }
135 : break;
136 :
137 0 : case FORCE_FIND:
138 : case GOT_ONE:
139 : {
140 : // traverse all children
141 0 : Traverser_CollisionTree::handle_group(group);
142 : }
143 0 : break;
144 : }
145 0 : }
146 :
147 0 : void Traverser_ProjectPoint::handle_boxed_group(BoxedGroupNode* boxedGroup)
148 : {
149 0 : SearchState tSearchState = m_searchState;
150 0 : switch(tSearchState)
151 : {
152 0 : case SEARCHING:
153 : // check whether the point lies inside the box.
154 : // If so traverse the group (all children).
155 0 : if(BoxBoundProbe(m_point, boxedGroup->min_corner(),
156 0 : boxedGroup->max_corner()))
157 : {
158 0 : handle_group(boxedGroup);
159 : }
160 : break;
161 :
162 0 : case FORCE_FIND:
163 0 : handle_group(boxedGroup);
164 0 : break;
165 :
166 0 : case GOT_ONE:
167 : // check whether the box around the point being projected, which
168 : // contains all points which could possibly be closer than the
169 : // temporarily closest point, intersects the boxedGroups bounding box.
170 0 : if(BoxBoxIntersection(boxedGroup->min_corner(),
171 0 : boxedGroup->max_corner(),
172 : m_boxMin, m_boxMax))
173 : {
174 0 : handle_group(boxedGroup);
175 : }
176 : break;
177 : }
178 0 : }
179 :
180 0 : void Traverser_ProjectPoint::
181 : handle_collision_edges(CollisionEdgesNode* colEdgesNode)
182 : {
183 0 : CollisionTreeRootNode* root = get_current_root_node();
184 0 : const vector3* pPoints = root->get_points();
185 0 : int numIndices = colEdgesNode->num_edges() * 2;
186 0 : const int* indices = colEdgesNode->get_edges();
187 :
188 0 : for(int i = 0; i < numIndices; i+=2)
189 : {
190 0 : const vector3& p1 = pPoints[indices[i]];
191 0 : const vector3& p2 = pPoints[indices[i+1]];
192 :
193 : number t;
194 0 : number distance = DistancePointToLine(t, m_point, p1, p2);
195 :
196 0 : if((m_searchState != GOT_ONE) || (distance < m_distance))
197 : {
198 0 : m_searchState = GOT_ONE;
199 0 : m_distance = distance;
200 0 : m_closestElemIndices[0] = indices[i];
201 0 : m_closestElemIndices[1] = indices[i+1];
202 0 : m_closestElemID = colEdgesNode->get_edge_id(i/2);
203 0 : m_closestElemType = 2;
204 0 : m_closestRootNode = root;
205 0 : VecScaleAdd(m_closestPoint, 1. - t, p1, t, p2);
206 :
207 : // reset the box
208 0 : m_boxMin.x() = m_point.x() - distance * 1.01;
209 0 : m_boxMin.y() = m_point.y() - distance * 1.01;
210 0 : m_boxMin.z() = m_point.z() - distance * 1.01;
211 0 : m_boxMax.x() = m_point.x() + distance * 1.01;
212 0 : m_boxMax.y() = m_point.y() + distance * 1.01;
213 0 : m_boxMax.z() = m_point.z() + distance * 1.01;
214 : }
215 : }
216 0 : }
217 :
218 0 : void Traverser_ProjectPoint::
219 : handle_collision_triangles(CollisionTrianglesNode* colTrisNode)
220 : {
221 0 : CollisionTreeRootNode* root = get_current_root_node();
222 0 : const vector3* pPoints = root->get_points();
223 0 : int numIndices = colTrisNode->num_triangles() * 3;
224 0 : const int* indices = colTrisNode->get_triangles();
225 :
226 0 : for(int i = 0; i < numIndices; i+=3)
227 : {
228 0 : const vector3& p1 = pPoints[indices[i]];
229 0 : const vector3& p2 = pPoints[indices[i+1]];
230 0 : const vector3& p3 = pPoints[indices[i+2]];
231 :
232 : vector3 n;
233 0 : CalculateTriangleNormalNoNormalize(n, p1, p2, p3);
234 :
235 : // if normal-check is enabled, we have to make sure, that the points
236 : // normal points into the same direction as the triangles normal.
237 0 : if(m_checkNormals){
238 0 : if(VecDot(n, m_pointNormal) <= 0)
239 0 : continue;
240 : }
241 :
242 : number bc1, bc2;
243 : vector3 vTmp;
244 0 : number distance = DistancePointToTriangle(vTmp, bc1, bc2,
245 0 : m_point, p1, p2, p3, n);
246 :
247 0 : if((m_searchState != GOT_ONE) || (distance < m_distance))
248 : {
249 0 : m_searchState = GOT_ONE;
250 0 : m_distance = distance;
251 0 : m_closestElemIndices[0] = indices[i];
252 0 : m_closestElemIndices[1] = indices[i+1];
253 0 : m_closestElemIndices[2] = indices[i+2];
254 0 : m_closestElemID = colTrisNode->get_triangle_id(i/3);
255 0 : m_closestElemType = 3;
256 0 : m_closestRootNode = root;
257 : m_closestPoint = vTmp;
258 :
259 : // reset the box
260 0 : m_boxMin.x() = m_point.x() - distance * 1.01;
261 0 : m_boxMin.y() = m_point.y() - distance * 1.01;
262 0 : m_boxMin.z() = m_point.z() - distance * 1.01;
263 0 : m_boxMax.x() = m_point.x() + distance * 1.01;
264 0 : m_boxMax.y() = m_point.y() + distance * 1.01;
265 0 : m_boxMax.z() = m_point.z() + distance * 1.01;
266 : }
267 : }
268 0 : }
269 :
270 : }// end of namespace node_tree
271 : }// end of namespace ug
|