Chi-Tech
SurfaceMeshLogicalVolume.cc
Go to the documentation of this file.
2
3#include "mesh/chi_mesh.h"
6
7#include "ChiObjectFactory.h"
8
9#include <utility>
10
11namespace chi_mesh
12{
13
15
17{
19
20 params.SetDocGroup("LuaLogicVolumes");
21
22 params.AddRequiredParameter<size_t>(
23 "surface_mesh_handle",
24 "Handle to a surface mesh that will represent this object");
25
26 return params;
27}
28
30 const chi::InputParameters& params)
31 : LogicalVolume(params),
32 surf_mesh(Chi::GetStackItemPtrAsType<chi_mesh::SurfaceMesh>(
33 Chi::object_stack,
34 params.GetParamValue<size_t>("surface_mesh_handle"),
35 __FUNCTION__)),
36 xbounds_({1.0e6, -1.0e6}),
37 ybounds_({1.0e6, -1.0e6}),
38 zbounds_({1.0e6, -1.0e6})
39{
40 const auto& vertices = surf_mesh->GetVertices();
41 for (auto& vertex : vertices)
42 {
43 const double x = vertex.x;
44 const double y = vertex.y;
45 const double z = vertex.z;
46 if (std::addressof(vertex) == std::addressof(vertices.front()))
47 {
48 xbounds_[0] = x;
49 xbounds_[1] = x;
50 ybounds_[0] = y;
51 ybounds_[1] = y;
52 zbounds_[0] = z;
53 zbounds_[1] = z;
54 }
55 else
56 {
57 xbounds_[0] = std::min(xbounds_[0],x);
58 xbounds_[1] = std::max(xbounds_[1],x);
59 ybounds_[0] = std::min(ybounds_[0],y);
60 ybounds_[1] = std::max(ybounds_[1],y);
61 zbounds_[0] = std::min(zbounds_[0],z);
62 zbounds_[1] = std::max(zbounds_[1],z);
63 }
64 }
65}
66
67// ###################################################################
68/**Logical operation for surface mesh.*/
70{
71 double tolerance = 1.0e-5;
72
73 //============================================= Boundbox check
74 double x = point.x;
75 double y = point.y;
76 double z = point.z;
77
78 if (not((x >= xbounds_[0]) and (x <= xbounds_[1]))) return false;
79 if (not((y >= ybounds_[0]) and (y <= ybounds_[1]))) return false;
80 if (not((z >= zbounds_[0]) and (z <= zbounds_[1]))) return false;
81
82 //============================================= Cheapshot pass
83 // This pass purely checks if the point have a
84 // negative sense with all the faces of the surface.
85 // If it does then .. bonus .. we don't need to do
86 // anything more because the surface is probably convex.
87 bool cheap_pass = true; // now try to disprove
88 for (auto& face : surf_mesh->GetTriangles())
89 {
90 chi_mesh::Vector3 fc = face.face_centroid;
91 chi_mesh::Vector3 p_to_fc = fc - point;
92
93 p_to_fc = p_to_fc / p_to_fc.Norm();
94
95 double sense = p_to_fc.Dot(face.geometric_normal);
96
97 if (sense < (0.0 - tolerance))
98 {
99 cheap_pass = false;
100 break;
101 }
102 } // for f
103
104 // if (!cheap_pass) return false;
105 if (cheap_pass) return true;
106
107 //============================================= Expensive pass
108 // Getting to here means the cheap pass produced
109 // a negative and now we need to do more work.
110 for (size_t f = 0; f < surf_mesh->GetTriangles().size(); f++)
111 {
112 chi_mesh::Vector3 fc = surf_mesh->GetTriangles()[f].face_centroid;
113 chi_mesh::Vector3 p_to_fc = fc - point;
114 double distance_to_face = p_to_fc.Norm();
115 double closest_distance = 1.0e16;
116 bool closest_sense_pos = false;
117
118 p_to_fc = p_to_fc / p_to_fc.Norm();
119
120 double sense = p_to_fc.Dot(surf_mesh->GetTriangles()[f].geometric_normal);
121
122 bool good_to_go = true;
123 if (sense < (0.0 - tolerance))
124 {
125 good_to_go = false;
126 for (size_t fi = 0; fi < surf_mesh->GetTriangles().size(); fi++)
127 {
128 if (fi == f) continue; // Skip same face
129
130 // Get all the vertices
131 int v0_i = surf_mesh->GetTriangles()[fi].v_index[0];
132 int v1_i = surf_mesh->GetTriangles()[fi].v_index[1];
133 int v2_i = surf_mesh->GetTriangles()[fi].v_index[2];
134 chi_mesh::Vertex v0 = surf_mesh->GetVertices()[v0_i];
135 chi_mesh::Vertex v1 = surf_mesh->GetVertices()[v1_i];
136 chi_mesh::Vertex v2 = surf_mesh->GetVertices()[v2_i];
137
138 //=========================== Check if the line intersects plane
139 chi_mesh::Vertex intp; // Intersection point
140 std::pair<double, double> weights;
141 bool intersects_plane = chi_mesh::CheckPlaneLineIntersect(
142 surf_mesh->GetTriangles()[fi].geometric_normal,
143 v0,
144 point,
145 fc,
146 intp,
147 &weights);
148 if (!intersects_plane) continue;
149
150 //=========================== Check if the line intersects the triangle
151 bool intersects_triangle = true;
152
153 // Compute the legs
154 chi_mesh::Vector3 v01 = v1 - v0;
155 chi_mesh::Vector3 v12 = v2 - v1;
156 chi_mesh::Vector3 v20 = v0 - v2;
157
158 // Compute the vertices to the point
159 chi_mesh::Vector3 v0p = intp - v0;
160 chi_mesh::Vector3 v1p = intp - v1;
161 chi_mesh::Vector3 v2p = intp - v2;
162
163 // Compute the cross products
164 chi_mesh::Vector3 x0p = v01.Cross(v0p);
165 chi_mesh::Vector3 x1p = v12.Cross(v1p);
166 chi_mesh::Vector3 x2p = v20.Cross(v2p);
167
168 // Normalize them
169 x0p = x0p / x0p.Norm();
170 x1p = x1p / x1p.Norm();
171 x2p = x2p / x2p.Norm();
172
173 chi_mesh::Vector3 face_norm =
174 surf_mesh->GetTriangles()[fi].geometric_normal /
175 surf_mesh->GetTriangles()[fi].geometric_normal.Norm();
176
177 if (x0p.Dot(face_norm) < 0.0) intersects_triangle = false;
178 if (x1p.Dot(face_norm) < 0.0) intersects_triangle = false;
179 if (x2p.Dot(face_norm) < 0.0) intersects_triangle = false;
180
181 if (!intersects_triangle) continue;
182
183 //============================ Determine the sense with the triangle
184 double sense_with_this_tri =
185 p_to_fc.Dot(surf_mesh->GetTriangles()[fi].geometric_normal);
186 double distance_to_triangle = weights.second * distance_to_face;
187
188 if (distance_to_triangle < closest_distance)
189 {
190 closest_distance = distance_to_triangle;
191
192 if (sense_with_this_tri > 0.0) closest_sense_pos = true;
193 else
194 closest_sense_pos = false;
195 } //
196
197 } // for inner iter face
198 } // if sense negative
199
200 if ((closest_distance < distance_to_face) && closest_sense_pos)
201 good_to_go = true;
202
203 if (!good_to_go) return false;
204 } // for f
205
206 return true;
207}
208
209} // namespace chi_mesh
void SetDocGroup(const std::string &doc_group)
void AddRequiredParameter(const std::string &name, const std::string &doc_string)
static chi::InputParameters GetInputParameters()
Definition: LogicalVolume.cc:6
bool Inside(const chi_mesh::Vector3 &point) const override
SurfaceMeshLogicalVolume(const chi::InputParameters &params)
static chi::InputParameters GetInputParameters()
bool CheckPlaneLineIntersect(const chi_mesh::Normal &plane_normal, const chi_mesh::Vector3 &plane_point, const chi_mesh::Vector3 &line_point_0, const chi_mesh::Vector3 &line_point_1, chi_mesh::Vector3 &intersection_point, std::pair< double, double > *weights=nullptr)
RegisterChiObject(chi_mesh, BooleanLogicalVolume)
double x
Element-0.
Vector3 Cross(const Vector3 &that) const
Vector3 Dot(const chi_mesh::TensorRank2Dim3 &that) const
double y
Element-1.
double z
Element-2.
double Norm() const