23 #define VERDICT_EXPORTS
37 int get_weight(
double& m11,
double& m21,
double& m12,
double& m22 )
64 if( coordinates[3][0] == coordinates[2][0] && coordinates[3][1] == coordinates[2][1] &&
65 coordinates[3][2] == coordinates[2][2] )
75 edges[0].
set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
76 coordinates[1][2] - coordinates[0][2] );
77 edges[1].
set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
78 coordinates[2][2] - coordinates[1][2] );
79 edges[2].
set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
80 coordinates[3][2] - coordinates[2][2] );
81 edges[3].
set( coordinates[0][0] - coordinates[3][0], coordinates[0][1] - coordinates[3][1],
82 coordinates[0][2] - coordinates[3][2] );
91 corner_normals[0] = edges[3] * edges[0];
92 corner_normals[1] = edges[0] * edges[1];
93 corner_normals[2] = edges[1] * edges[2];
94 corner_normals[3] = edges[2] * edges[3];
98 principal_axes[0] = edges[0] - edges[2];
99 principal_axes[1] = edges[1] - edges[3];
103 unit_center_normal = principal_axes[0] * principal_axes[1];
106 areas[0] = unit_center_normal % corner_normals[0];
107 areas[1] = unit_center_normal % corner_normals[1];
108 areas[2] = unit_center_normal % corner_normals[2];
109 areas[3] = unit_center_normal % corner_normals[3];
124 VerdictVector global[4] = { nodes[0], nodes[1], nodes[2], nodes[3] };
127 for( i = 0; i < 4; i++ )
136 for( i = 0; i < 4; i++ )
139 vector2 = global[( i + 1 ) % 4];
140 vector_diff = vector2 - vector1;
141 ref_point += vector1;
142 vector_sum = vector1 + vector2;
144 tmp_vector.
set( vector_diff.y() * vector_sum.
z(), vector_diff.z() * vector_sum.
x(),
145 vector_diff.x() * vector_sum.
y() );
146 normal += tmp_vector;
158 for( i = 0; i < 4; i++ )
160 nodes[i].
x( global[i] % local_x_axis );
161 nodes[i].
y( global[i] % local_y_axis );
162 nodes[i].
z( global[i] % normal );
174 centroid += node_pos[1];
175 centroid += node_pos[2];
176 centroid += node_pos[3];
180 node_pos[0] -= centroid;
181 node_pos[1] -= centroid;
182 node_pos[2] -= centroid;
183 node_pos[3] -= centroid;
185 VerdictVector rotate = node_pos[1] + node_pos[2] - node_pos[3] - node_pos[0];
188 double cosine = rotate.
x();
189 double sine = rotate.
y();
193 for(
int i = 0; i < 4; i++ )
195 xnew = cosine * node_pos[i].
x() + sine * node_pos[i].
y();
196 node_pos[i].
y( -sine * node_pos[i].x() + cosine * node_pos[i].y() );
197 node_pos[i].
x( xnew );
209 edge0.
set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
210 coordinates[1][2] - coordinates[0][2] );
212 edge1.
set( coordinates[3][0] - coordinates[0][0], coordinates[3][1] - coordinates[0][1],
213 coordinates[3][2] - coordinates[0][2] );
221 edge0.
set( coordinates[2][0] - coordinates[3][0], coordinates[2][1] - coordinates[3][1],
222 coordinates[2][2] - coordinates[3][2] );
224 edge1.
set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
225 coordinates[2][2] - coordinates[1][2] );
232 if( ( norm0 % norm2 ) > 0.0 )
241 edge0.
set( coordinates[1][0] - coordinates[2][0], coordinates[1][1] - coordinates[2][1],
242 coordinates[1][2] - coordinates[2][2] );
244 edge1.
set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
245 coordinates[1][2] - coordinates[0][2] );
250 if( ( norm0 % norm1 ) > 0.0 )
281 double mab, Mab, mcd, Mcd, m2, M2;
302 m2 = mab < mcd ? mab : mcd;
303 M2 = Mab > Mcd ? Mab : Mcd;
309 double edge_ratio = sqrt( M2 / m2 );
324 quad_nodes[0].
set( coordinates[0][0], coordinates[0][1], coordinates[0][2] );
325 quad_nodes[1].
set( coordinates[1][0], coordinates[1][1], coordinates[1][2] );
326 quad_nodes[2].
set( coordinates[2][0], coordinates[2][1], coordinates[2][2] );
327 quad_nodes[3].
set( coordinates[3][0], coordinates[3][1], coordinates[3][2] );
330 principal_axes[0] = quad_nodes[1] + quad_nodes[2] - quad_nodes[0] - quad_nodes[3];
331 principal_axes[1] = quad_nodes[2] + quad_nodes[3] - quad_nodes[0] - quad_nodes[1];
333 double len1 = principal_axes[0].
length();
334 double len2 = principal_axes[1].
length();
338 double max_edge_ratio =
VERDICT_MAX( len1 / len2, len2 / len1 );
357 double a1 = edges[0].
length();
358 double b1 = edges[1].
length();
359 double c1 = edges[2].
length();
360 double d1 = edges[3].
length();
362 double ma = a1 > b1 ? a1 : b1;
363 double mb = c1 > d1 ? c1 : d1;
364 double hm = ma >
mb ? ma :
mb;
372 double aspect_ratio = .5 * hm * ( a1 + b1 + c1 + d1 ) / denominator;
388 static const double normal_coeff = 1. / ( 2. * sqrt( 2. ) );
399 diag.
set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
400 coordinates[2][2] - coordinates[0][2] );
403 diag.
set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
404 coordinates[3][2] - coordinates[1][2] );
407 double t0 = a2 > b2 ? a2 : b2;
408 double t1 = c2 > d2 ? c2 : d2;
409 double t2 = m2 > n2 ? m2 : n2;
410 double h2 = t0 > t1 ? t0 : t1;
411 h2 = h2 > t2 ? h2 : t2;
423 t0 = t0 < t1 ? t0 : t1;
424 t2 = t2 < t3 ? t2 : t3;
425 t0 = t0 < t2 ? t0 : t2;
429 double radius_ratio = normal_coeff * sqrt( ( a2 + b2 + c2 + d2 ) * h2 ) / t0;
466 double qsum = ( a2 + b2 ) / ab1;
467 qsum += ( b2 + c2 ) / bc1;
468 qsum += ( c2 + d2 ) / cd1;
469 qsum += ( d2 + a2 ) / da1;
471 double med_aspect_frobenius = .125 * qsum;
508 double qmax = ( a2 + b2 ) / ab1;
510 double qcur = ( b2 + c2 ) / bc1;
511 qmax = qmax > qcur ? qmax : qcur;
513 qcur = ( c2 + d2 ) / cd1;
514 qmax = qmax > qcur ? qmax : qcur;
516 qcur = ( d2 + a2 ) / da1;
517 qmax = qmax > qcur ? qmax : qcur;
519 double max_aspect_frobenius = .5 * qmax;
533 for(
int i = 0; i < 4; i++ )
534 node_pos[i].set( coordinates[i][0], coordinates[i][1], coordinates[i][2] );
537 principle_axes[0] = node_pos[1] + node_pos[2] - node_pos[3] - node_pos[0];
538 principle_axes[1] = node_pos[2] + node_pos[3] - node_pos[0] - node_pos[1];
543 double skew = fabs( principle_axes[0] % principle_axes[1] );
556 for(
int i = 0; i < 4; i++ )
557 node_pos[i].set( coordinates[i][0], coordinates[i][1], coordinates[i][2] );
560 principle_axes[0] = node_pos[1] + node_pos[2] - node_pos[3] - node_pos[0];
561 principle_axes[1] = node_pos[2] + node_pos[3] - node_pos[0] - node_pos[1];
563 VerdictVector cross_derivative = node_pos[0] + node_pos[2] - node_pos[1] - node_pos[3];
566 lengths[0] = principle_axes[0].
length();
567 lengths[1] = principle_axes[1].
length();
570 lengths[0] =
VERDICT_MIN( lengths[0], lengths[1] );
574 double taper = cross_derivative.
length() / lengths[0];
590 corner_normals[0] = edges[3] * edges[0];
591 corner_normals[1] = edges[0] * edges[1];
592 corner_normals[2] = edges[1] * edges[2];
593 corner_normals[3] = edges[2] * edges[3];
600 pow(
VERDICT_MIN( corner_normals[0] % corner_normals[2], corner_normals[1] % corner_normals[3] ), 3 );
614 double corner_areas[4];
617 double area = 0.25 * ( corner_areas[0] + corner_areas[1] + corner_areas[2] + corner_areas[3] );
633 double lengths_squared[4];
639 temp.
set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
640 coordinates[2][2] - coordinates[0][2] );
643 temp.
set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
644 coordinates[3][2] - coordinates[1][2] );
647 static const double QUAD_STRETCH_FACTOR = sqrt( 2.0 );
658 VERDICT_MIN( lengths_squared[2], lengths_squared[3] ) ) /
678 double max_angle = 0.0;
681 edges[0].
set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
682 coordinates[1][2] - coordinates[0][2] );
683 edges[1].
set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
684 coordinates[2][2] - coordinates[1][2] );
685 edges[2].
set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
686 coordinates[3][2] - coordinates[2][2] );
687 edges[3].
set( coordinates[0][0] - coordinates[3][0], coordinates[0][1] - coordinates[3][1],
688 coordinates[0][2] - coordinates[3][2] );
720 if( areas[0] < 0 || areas[1] < 0 || areas[2] < 0 || areas[3] < 0 )
722 max_angle = 360 - max_angle;
741 double min_angle = 360.0;
744 edges[0].
set( coordinates[1][0] - coordinates[0][0], coordinates[1][1] - coordinates[0][1],
745 coordinates[1][2] - coordinates[0][2] );
746 edges[1].
set( coordinates[2][0] - coordinates[1][0], coordinates[2][1] - coordinates[1][1],
747 coordinates[2][2] - coordinates[1][2] );
748 edges[2].
set( coordinates[3][0] - coordinates[2][0], coordinates[3][1] - coordinates[2][1],
749 coordinates[3][2] - coordinates[2][2] );
750 edges[3].
set( coordinates[0][0] - coordinates[3][0], coordinates[0][1] - coordinates[3][1],
751 coordinates[0][2] - coordinates[3][2] );
791 double max_oddy = 0.;
795 double g, g11, g12, g22, cur_oddy;
798 for( i = 0; i < 4; i++ )
799 node_pos[i].set( coordinates[i][0], coordinates[i][1], coordinates[i][2] );
801 for( i = 0; i < 4; i++ )
803 first = node_pos[i] - node_pos[( i + 1 ) % 4];
804 second = node_pos[i] - node_pos[( i + 3 ) % 4];
807 g12 =
first % second;
808 g22 = second % second;
809 g = g11 * g22 - g12 * g12;
814 cur_oddy = ( ( g11 - g22 ) * ( g11 - g22 ) + 4. * g12 * g12 ) / 2. / g;
836 double max_condition = 0.;
842 for(
int i = 0; i < 4; i++ )
845 xxi.
set( coordinates[i][0] - coordinates[( i + 1 ) % 4][0], coordinates[i][1] - coordinates[( i + 1 ) % 4][1],
846 coordinates[i][2] - coordinates[( i + 1 ) % 4][2] );
848 xet.
set( coordinates[i][0] - coordinates[( i + 3 ) % 4][0], coordinates[i][1] - coordinates[( i + 3 ) % 4][1],
849 coordinates[i][2] - coordinates[( i + 3 ) % 4][2] );
854 condition = ( xxi % xxi + xet % xet ) / areas[i];
856 max_condition =
VERDICT_MAX( max_condition, condition );
908 scaled_jac = corner_areas[0] / (
length[0] *
length[3] );
909 min_scaled_jac =
VERDICT_MIN( scaled_jac, min_scaled_jac );
911 scaled_jac = corner_areas[1] / (
length[1] *
length[0] );
912 min_scaled_jac =
VERDICT_MIN( scaled_jac, min_scaled_jac );
914 scaled_jac = corner_areas[2] / (
length[2] *
length[1] );
915 min_scaled_jac =
VERDICT_MIN( scaled_jac, min_scaled_jac );
917 scaled_jac = corner_areas[3] / (
length[3] *
length[2] );
918 min_scaled_jac =
VERDICT_MIN( scaled_jac, min_scaled_jac );
995 double w11, w21, w12, w22;
997 double avg_area =
determinant( w11, w21, w12, w22 );
1002 w11 = quad_area / avg_area;
1007 rel_size *= rel_size;
1026 double shape_and_size = shape *
size;
1043 double shear_and_size = shear *
size;
1060 double element_area = 0.0, distrt, thickness_gauss;
1061 double cur_jacobian = 0., sign_jacobian, jacobian;
1065 int number_of_gauss_points = 0;
1066 if( num_nodes == 4 )
1068 number_of_gauss_points = 2;
1070 else if( num_nodes == 8 )
1072 number_of_gauss_points = 3;
1075 int total_number_of_gauss_points = number_of_gauss_points * number_of_gauss_points;
1087 for( i = 0; i < 3; i++ )
1090 first.set( coordinates[i][0] - coordinates[( i + 1 ) % 3][0],
1091 coordinates[i][1] - coordinates[( i + 1 ) % 3][1],
1092 coordinates[i][2] - coordinates[( i + 1 ) % 3][2] );
1094 second.
set( coordinates[i][0] - coordinates[( i + 2 ) % 3][0],
1095 coordinates[i][1] - coordinates[( i + 2 ) % 3][1],
1096 coordinates[i][2] - coordinates[( i + 2 ) % 3][2] );
1098 sign_jacobian = ( face_normal % (
first * second ) ) > 0 ? 1. : -1.;
1099 cur_jacobian = sign_jacobian * (
first * second ).
length();
1100 distortion =
VERDICT_MIN( distortion, cur_jacobian );
1103 distortion /= element_area;
1119 for( ife = 0; ife < total_number_of_gauss_points; ife++ )
1121 aa.
set( 0.0, 0.0, 0.0 );
1122 bb.
set( 0.0, 0.0, 0.0 );
1124 for( ja = 0; ja < num_nodes; ja++ )
1126 xin.
set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] );
1127 aa += dndy1[ife][ja] * xin;
1128 bb += dndy2[ife][ja] * xin;
1130 normal_at_point = aa * bb;
1131 jacobian = normal_at_point.
length();
1132 element_area += weight[ife] * jacobian;
1144 for( ja = 0; ja < num_nodes; ja++ )
1146 aa.
set( 0.0, 0.0, 0.0 );
1147 bb.
set( 0.0, 0.0, 0.0 );
1148 for( jai = 0; jai < num_nodes; jai++ )
1150 xin.
set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] );
1151 aa += dndy1_at_node[ja][jai] * xin;
1152 bb += dndy2_at_node[ja][jai] * xin;
1154 normal_at_nodes[ja] = aa * bb;
1159 bool flat_element =
true;
1162 for( ja = 0; ja < num_nodes; ja++ )
1164 dot_product = normal_at_nodes[0] % normal_at_nodes[ja];
1167 flat_element =
false;
1175 thickness = 0.001 * sqrt( element_area );
1178 double zl = 0.5773502691896;
1179 if( flat_element ) zl = 0.0;
1181 int no_gauss_pts_z = ( flat_element ) ? 1 : 2;
1185 for( ife = 0; ife < total_number_of_gauss_points; ife++ )
1188 for( igz = 0; igz < no_gauss_pts_z; igz++ )
1191 thickness_z = zl * thickness / 2.0;
1193 aa.
set( 0.0, 0.0, 0.0 );
1194 bb.
set( 0.0, 0.0, 0.0 );
1195 cc.
set( 0.0, 0.0, 0.0 );
1197 for( ja = 0; ja < num_nodes; ja++ )
1199 xin.
set( coordinates[ja][0], coordinates[ja][1], coordinates[ja][2] );
1200 xin += thickness_z * normal_at_nodes[ja];
1201 aa += dndy1[ife][ja] * xin;
1202 bb += dndy2[ife][ja] * xin;
1203 thickness_gauss = shape_function[ife][ja] * thickness / 2.0;
1204 cc += thickness_gauss * normal_at_nodes[ja];
1207 normal_at_point = aa * bb;
1209 distrt = cc % normal_at_point;
1210 if( distrt < distortion ) distortion = distrt;
1215 for( ja = 0; ja < num_nodes; ja++ )
1217 for( igz = 0; igz < no_gauss_pts_z; igz++ )
1220 thickness_z = zl * thickness / 2.0;
1222 aa.
set( 0.0, 0.0, 0.0 );
1223 bb.
set( 0.0, 0.0, 0.0 );
1224 cc.
set( 0.0, 0.0, 0.0 );
1226 for( jai = 0; jai < num_nodes; jai++ )
1228 xin.
set( coordinates[jai][0], coordinates[jai][1], coordinates[jai][2] );
1229 xin += thickness_z * normal_at_nodes[ja];
1230 aa += dndy1_at_node[ja][jai] * xin;
1231 bb += dndy2_at_node[ja][jai] * xin;
1233 thickness_gauss = thickness / 2.0;
1235 thickness_gauss = 0.;
1236 cc += thickness_gauss * normal_at_nodes[jai];
1239 normal_at_point = aa * bb;
1240 sign_jacobian = ( face_normal % normal_at_point ) > 0 ? 1. : -1.;
1241 distrt = sign_jacobian * ( cc % normal_at_point );
1243 if( distrt < distortion ) distortion = distrt;
1246 if( element_area * thickness != 0 )
1247 distortion *= 8. / ( element_area * thickness );
1252 return (
double)distortion;
1259 double coordinates[][3],
1260 unsigned int metrics_request_flag,
1289 lengths[0] = edges[0].
length();
1290 lengths[1] = edges[1].
length();
1291 lengths[2] = edges[2].
length();
1292 lengths[3] = edges[3].
length();
1315 angles[0] = acos( -( edges[0] % edges[1] ) / ( lengths[0] * lengths[1] ) );
1316 angles[1] = acos( -( edges[1] % edges[2] ) / ( lengths[1] * lengths[2] ) );
1317 angles[2] = acos( -( edges[2] % edges[3] ) / ( lengths[2] * lengths[3] ) );
1318 angles[3] = acos( -( edges[3] % edges[0] ) / ( lengths[3] * lengths[0] ) );
1332 for(
int i = 0; i < 4; i++ )
1340 for(
int i = 0; i < 4; i++ )
1344 if( areas[0] < 0 || areas[1] < 0 || areas[2] < 0 || areas[3] < 0 )
1355 principal_axes[0] = edges[0] - edges[2];
1356 principal_axes[1] = edges[1] - edges[3];
1360 double len1 = principal_axes[0].
length();
1361 double len2 = principal_axes[1].
length();
1382 metric_vals->
taper = cross_derivative.
length() / min_length;
1389 metric_vals->
skew = 0.0;
1391 metric_vals->
skew = fabs( principal_axes[0] % principal_axes[1] );
1399 metric_vals->
area = 0.25 * ( areas[0] + areas[1] + areas[2] + areas[3] );
1407 double w11, w21, w12, w22;
1409 double avg_area =
determinant( w11, w21, w12, w22 );
1432 metric_vals->
shear = 0.0;
1436 scaled_jac = areas[0] / ( lengths[0] * lengths[3] );
1437 min_scaled_jac =
VERDICT_MIN( scaled_jac, min_scaled_jac );
1439 scaled_jac = areas[1] / ( lengths[1] * lengths[0] );
1440 min_scaled_jac =
VERDICT_MIN( scaled_jac, min_scaled_jac );
1442 scaled_jac = areas[2] / ( lengths[2] * lengths[1] );
1443 min_scaled_jac =
VERDICT_MIN( scaled_jac, min_scaled_jac );
1445 scaled_jac = areas[3] / ( lengths[3] * lengths[2] );
1446 min_scaled_jac =
VERDICT_MIN( scaled_jac, min_scaled_jac );
1452 metric_vals->
shear = 0.0;
1454 metric_vals->
shear = min_scaled_jac;
1461 corner_normals[0] = edges[3] * edges[0];
1462 corner_normals[1] = edges[0] * edges[1];
1463 corner_normals[2] = edges[1] * edges[2];
1464 corner_normals[3] = edges[2] * edges[3];
1468 double oddy, max_oddy = 0.0;
1470 double diff, dot_prod;
1483 diff = ( lengths[0] * lengths[0] ) - ( lengths[1] * lengths[1] );
1484 dot_prod = edges[0] % edges[1];
1485 oddy = ( ( diff * diff ) + 4 * dot_prod * dot_prod ) / ( 2 *
length_squared[1] );
1488 diff = ( lengths[1] * lengths[1] ) - ( lengths[2] * lengths[2] );
1489 dot_prod = edges[1] % edges[2];
1490 oddy = ( ( diff * diff ) + 4 * dot_prod * dot_prod ) / ( 2 *
length_squared[2] );
1493 diff = ( lengths[2] * lengths[2] ) - ( lengths[3] * lengths[3] );
1494 dot_prod = edges[2] % edges[3];
1495 oddy = ( ( diff * diff ) + 4 * dot_prod * dot_prod ) / ( 2 *
length_squared[3] );
1498 diff = ( lengths[3] * lengths[3] ) - ( lengths[0] * lengths[0] );
1499 dot_prod = edges[3] % edges[0];
1500 oddy = ( ( diff * diff ) + 4 * dot_prod * dot_prod ) / ( 2 *
length_squared[0] );
1503 metric_vals->
oddy = max_oddy;
1515 pow(
VERDICT_MIN( corner_normals[0] % corner_normals[2], corner_normals[1] % corner_normals[3] ),
1525 temp.
set( coordinates[2][0] - coordinates[0][0], coordinates[2][1] - coordinates[0][1],
1526 coordinates[2][2] - coordinates[0][2] );
1529 temp.
set( coordinates[3][0] - coordinates[1][0], coordinates[3][1] - coordinates[1][1],
1530 coordinates[3][2] - coordinates[1][2] );
1533 static const double QUAD_STRETCH_FACTOR = sqrt( 2.0 );
1542 QUAD_STRETCH_FACTOR *
1549 double lengths_squared[4];
1559 metric_vals->
shape = 0.0;
1563 double max_condition = 0.0, condition;
1565 condition = ( lengths_squared[0] + lengths_squared[3] ) / areas[0];
1566 max_condition =
VERDICT_MAX( max_condition, condition );
1568 condition = ( lengths_squared[1] + lengths_squared[0] ) / areas[1];
1569 max_condition =
VERDICT_MAX( max_condition, condition );
1571 condition = ( lengths_squared[2] + lengths_squared[1] ) / areas[2];
1572 max_condition =
VERDICT_MAX( max_condition, condition );
1574 condition = ( lengths_squared[3] + lengths_squared[2] ) / areas[3];
1575 max_condition =
VERDICT_MAX( max_condition, condition );
1577 metric_vals->
condition = 0.5 * max_condition;
1578 metric_vals->
shape = 2 / max_condition;
1697 if( metric_vals->
stretch > 0 )
1710 if( metric_vals->
warpage > 0 )