1 /*=========================================================================
2 *
3 * Copyright Insight Software Consortium
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0.txt
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *=========================================================================*/
18
19 #include "itkFEMElement2DC0LinearLine.h"
20
21 namespace itk
22 {
23 namespace fem
24 {
25 void
26 Element2DC0LinearLine
GetIntegrationPointAndWeight(unsigned int i,VectorType & pt,Float & w,unsigned int order) const27 ::GetIntegrationPointAndWeight(unsigned int i, VectorType & pt, Float & w, unsigned int order) const
28 {
29
30 // default integration order
31 if( ( order == 0 ) || (order >= Element::gaussMaxOrder) )
32 {
33 order = DefaultIntegrationOrder;
34 }
35
36 pt.set_size(1);
37
38 pt[0] = gaussPoint[order][i];
39 w = gaussWeight[order][i];
40 }
41
42 unsigned int
43 Element2DC0LinearLine
GetNumberOfIntegrationPoints(unsigned int order) const44 ::GetNumberOfIntegrationPoints(unsigned int order) const
45 {
46 // default integration order
47 if( ( order == 0 ) || (order >= Element::gaussMaxOrder) )
48 {
49 order = DefaultIntegrationOrder;
50 }
51
52 return order;
53 }
54
55 Element2DC0LinearLine::VectorType
56 Element2DC0LinearLine
ShapeFunctions(const VectorType & pt) const57 ::ShapeFunctions(const VectorType & pt) const
58 {
59 /* Linear Line element has two shape functions */
60 VectorType shapeF(2);
61
62 shapeF[0] = 0.5 - pt[0] / 2.0;
63 shapeF[1] = 0.5 + pt[0] / 2.0;
64
65 return shapeF;
66 }
67
68 void
69 Element2DC0LinearLine
ShapeFunctionDerivatives(const VectorType &,MatrixType & shapeD) const70 ::ShapeFunctionDerivatives(const VectorType &, MatrixType & shapeD) const
71 {
72 shapeD.set_size(1, 2);
73
74 shapeD[0][0] = -0.5;
75 shapeD[0][1] = 0.5;
76 }
77
78 void
79 Element2DC0LinearLine
Jacobian(const VectorType &,MatrixType & J,const MatrixType *) const80 ::Jacobian(const VectorType &, MatrixType & J, const MatrixType *) const
81 {
82 // Since the line element defines only one global coordinate
83 // and lives in 2D space, we need to provide a custom Jacobian.
84 J.set_size(1, 1);
85
86 // Get the length of the element
87 // Note: This simple implementation is only valid for linear line elements.
88 // For higher order elements we must integrate to obtain the exact
89 // element length
90 Float l = ( this->m_node[1]->GetCoordinates() - this->m_node[0]->GetCoordinates() ).magnitude();
91 J[0][0] = l / 2;
92 }
93
94 bool
95 Element2DC0LinearLine
GetLocalFromGlobalCoordinates(const VectorType & globalPt,VectorType & pcoords) const96 ::GetLocalFromGlobalCoordinates(const VectorType & globalPt, VectorType & pcoords) const
97 {
98 VectorType closestPoint(3);
99
100 pcoords[1] = 0.0;
101 pcoords[2] = 0.0;
102
103 // get the length of the element
104 const Float l = ( this->m_node[1]->GetCoordinates() - this->m_node[0]->GetCoordinates() ).magnitude();
105
106 // tolerance is based on the length of the element
107 const Float tol = l * l * 1e-8;
108
109 const VectorType a1 = this->m_node[0]->GetCoordinates();
110 const VectorType a2 = this->m_node[1]->GetCoordinates();
111
112 // DistanceToLine sets pcoords[0] to a value t, 0 <= t <= 1
113 const Float dist2 = this->DistanceToLine(globalPt, a1, a2, pcoords[0], closestPoint);
114
115 // if the distance specified is more than the tolerance
116 if( ( dist2 <= tol ) && ( pcoords[0] >= 0.0 ) && ( pcoords[0] <= 1.0 ) )
117 {
118 return true;
119 }
120 return false;
121 }
122
123 // ----------------------------------------------------------------------------
124 // Compute distance to finite line. Returns parametric coordinate t
125 // and point location on line.
DistanceToLine(const VectorType & x,const VectorType & p1,const VectorType & p2,Float & t,VectorType & closestPoint) const126 itk::fem::Element::Float Element2DC0LinearLine::DistanceToLine(
127 const VectorType & x, const VectorType & p1, const VectorType & p2, Float & t,
128 VectorType & closestPoint) const
129 {
130 Float denom, num;
131 VectorType p21(3);
132 VectorType closest;
133 Float tolerance;
134
135 //
136 // Determine appropriate vectors
137 //
138 p21[0] = p2[0] - p1[0];
139 p21[1] = p2[1] - p1[1];
140 p21[2] = p2[2] - p1[2];
141
142 //
143 // Get parametric location
144 //
145 num = p21[0] * (x[0] - p1[0]) + p21[1] * (x[1] - p1[1]) + p21[2] * (x[2] - p1[2]);
146 denom = p21[0] * p21[0] + p21[1] * p21[1] + p21[2] * p21[2];
147
148 // trying to avoid an expensive fabs
149 tolerance = 1e-5 * num;
150 if( tolerance < 0.0 )
151 {
152 tolerance = -tolerance;
153 }
154 if( -tolerance < denom && denom < tolerance ) // numerically bad!
155 {
156 closest = p1; // arbitrary, point is (numerically) far away
157 }
158 //
159 // If parametric coordinate is within 0<=p<=1, then the point is closest to
160 // the line. Otherwise, it's closest to a point at the end of the line.
161 //
162 else if( denom <= 0.0 || (t = num / denom) < 0.0 )
163 {
164 closest = p1;
165 }
166 else if( t > 1.0 )
167 {
168 closest = p2;
169 }
170 else
171 {
172 closest = p21;
173 p21[0] = p1[0] + t * p21[0];
174 p21[1] = p1[1] + t * p21[1];
175 p21[2] = p1[2] + t * p21[2];
176 }
177
178 closestPoint[0] = closest[0];
179 closestPoint[1] = closest[1];
180 closestPoint[2] = closest[2];
181 Float dist = (x[0] - closestPoint[0]) * (x[0] - closestPoint[0])
182 + (x[1] - closestPoint[1]) * (x[1] - closestPoint[1]) + (x[2] - closestPoint[2]) * (x[2] - closestPoint[2]);
183 return dist;
184 }
185
PopulateEdgeIds()186 void Element2DC0LinearLine::PopulateEdgeIds()
187 {
188 this->m_EdgeIds.resize(0);
189
190 std::vector<int> edgePtIds;
191 edgePtIds.resize(2);
192
193 // edge 0
194 edgePtIds[0] = 0;
195 edgePtIds[1] = 1;
196 this->m_EdgeIds.push_back(edgePtIds);
197 }
198
PrintSelf(std::ostream & os,Indent indent) const199 void Element2DC0LinearLine::PrintSelf(std::ostream& os, Indent indent) const
200 {
201 Superclass::PrintSelf(os, indent);
202 }
203
204 } // end namespace fem
205 } // end namespace itk
206