MeshKit
1.0
|
00001 #include "meshkit/AF2PlaneProjection.hpp" 00002 00003 // C++ 00004 #include <cmath> 00005 00006 // CGM 00007 #include "CubitDefines.h" 00008 #include "CubitVector.hpp" 00009 #include "RefFace.hpp" 00010 #include "Surface.hpp" 00011 00012 // MeshKit 00013 #include "meshkit/Error.hpp" 00014 #include "meshkit/iGeom.hpp" 00015 #include "meshkit/VecUtil.hpp" 00016 00017 AF2PlaneProjection::AF2PlaneProjection(iGeom* iGeomPtrArg, 00018 iGeom::EntityHandle srfcHandle, 00019 MeshKit::Vector<3> const & planeOrigin, 00020 MeshKit::Vector<3> const & planeNormal, 00021 MeshKit::Vector<3> const & planeXDir, 00022 double scaleFactor) : 00023 iGeomPtr(iGeomPtrArg), 00024 surface(srfcHandle), 00025 pOrigin(planeOrigin), 00026 pNormal(planeNormal), 00027 pXDir(planeXDir) 00028 { 00029 // exercise the iGeom pointer and check that the entity is a face 00030 iBase_EntityType eTypeResult; 00031 MeshKit::IBERRCHK(iGeomPtr->getEntType(surface, eTypeResult), *iGeomPtr); 00032 if (eTypeResult != iBase_FACE) 00033 { 00034 throw MeshKit::Error(MeshKit::MK_BAD_INPUT, "Geometry entity handle does not refer to a surface in AF2PlaneProjection constructor."); 00035 } 00036 00037 // compute the squared length of the normal vector 00038 double nvNormSqrd = pNormal[0] * pNormal[0] + 00039 pNormal[1] * pNormal[1] + pNormal[2] * pNormal[2]; 00040 00041 // check that the length is sufficiently non-zero 00042 if (std::fabs(nvNormSqrd) < 1.0e-16) 00043 { 00044 throw MeshKit::Error(MeshKit::MK_BAD_INPUT, "Normal vector length is near zero in AF2PlaneProjection constructor."); 00045 } 00046 00047 // normalize the normal vector to have length one, if necessary 00048 if (std::fabs(nvNormSqrd - 1.0) > 1.0e-8) 00049 { 00050 pNormal *= 1.0 / std::sqrt(nvNormSqrd); 00051 } 00052 00053 // compute the squared length of the x-direction vector 00054 double xdvNormSqrd = pXDir[0] * pXDir[0] + 00055 pXDir[1] * pXDir[1] + pXDir[2] * pXDir[2]; 00056 00057 // check that the length is sufficiently non-zero 00058 if (std::fabs(xdvNormSqrd) < 1.0e-16) 00059 { 00060 throw MeshKit::Error(MeshKit::MK_BAD_INPUT, "X-direction vector length is near zero in AF2PlaneProjection constructor."); 00061 } 00062 00063 // normalize the x-direction vector to have length one, if necessary 00064 if (std::fabs(xdvNormSqrd - 1.0) > 1.0e-8) 00065 { 00066 pXDir *= 1.0 / std::sqrt(xdvNormSqrd); 00067 } 00068 00069 double nxDot = MeshKit::VecUtil::dot((double*)pNormal.data(), 00070 (double*)pXDir.data()); 00071 if (std::fabs(nxDot) > 1.0e-12) 00072 { 00073 throw MeshKit::Error(MeshKit::MK_BAD_INPUT, "X-direction vector is not normal to the normal vector in AF2PlaneProjection constructor."); 00074 } 00075 00076 // compute the y-direction vector 00077 MeshKit::VecUtil::cross((double*)pNormal.data(), (double*)pXDir.data(), 00078 (double*)pYDir.data()); 00079 00080 if (scaleFactor <= 0.0) 00081 { 00082 throw MeshKit::Error(MeshKit::MK_BAD_INPUT, 00083 "Scale factor is not positive."); 00084 } 00085 scale = 1.0 / scaleFactor; 00086 } 00087 00088 AF2Point2D* AF2PlaneProjection::transformFromSurface( 00089 AF2Point3D const & srfcPnt, bool & legal) const 00090 { 00091 double diffX = srfcPnt.getX() - pOrigin[0]; 00092 double diffY = srfcPnt.getY() - pOrigin[1]; 00093 double diffZ = srfcPnt.getZ() - pOrigin[2]; 00094 00095 double diffDotNormal = diffX * pNormal[0] + 00096 diffY * pNormal[1] + diffZ * pNormal[2]; 00097 double normalCmpX = diffDotNormal * pNormal[0]; 00098 double normalCmpY = diffDotNormal * pNormal[1]; 00099 double normalCmpZ = diffDotNormal * pNormal[2]; 00100 00101 double planarCmpX = diffX - normalCmpX; 00102 double planarCmpY = diffY - normalCmpY; 00103 double planarCmpZ = diffZ - normalCmpZ; 00104 00105 double planePntX = scale * (planarCmpX * pXDir[0] + 00106 planarCmpY * pXDir[1] + planarCmpZ * pXDir[2]); 00107 double planePntY = scale * (planarCmpX * pYDir[0] + 00108 planarCmpY * pYDir[1] + planarCmpZ * pYDir[2]); 00109 00110 // compute normal at the surface point; if too different orientation, we should not 00111 // consider the point legal 00112 // maybe we should keep the normal to the points on the front available always, we repeat this too much 00113 double normalX, normalY, normalZ; 00114 iGeomPtr->getEntNrmlXYZ(surface, srfcPnt.getX(), srfcPnt.getY(), 00115 srfcPnt.getZ(), normalX, normalY, normalZ); 00116 // normalize? 00117 double sqrN= sqrt(normalX*normalX + normalY*normalY + normalZ*normalZ); 00118 if (sqrN<=1.e-12) 00119 legal= false; 00120 else 00121 { 00122 normalX/=sqrN; normalY/=sqrN; normalZ/=sqrN; 00123 double nrmlDot = normalX * pNormal[0] + 00124 normalY * pNormal[1] + normalZ * pNormal[2]; 00125 00126 if (nrmlDot < 0.0009765625) // 1.0/1024 == 0.0009765625) 00127 legal= false; 00128 } 00129 00130 return new AF2Point2D(planePntX, planePntY); 00131 } 00132 00133 AF2Point3D* AF2PlaneProjection::transformToSurface( 00134 AF2Point2D const & planePnt, unsigned long const & pntId) const 00135 { 00136 MeshKit::Vector<3> rayOrigin(pOrigin); 00137 rayOrigin += (planePnt.getX() / scale) * pXDir + 00138 (planePnt.getY() / scale) * pYDir; 00139 /* // we are looking for the point on the surface, within some distance away 00140 // from our plane; 00141 const double MYTOL = 1.e-7; 00142 // maxDistanceFromPlane is a good measure of how far is the surface from the projection plane 00143 double alfa = 1000*MYTOL + 3.0*maxDistanceFromPlane; 00144 if (alfa >2.0) 00145 alfa =2.0; // do not go overboard 00146 if (alfa < 0.5) 00147 alfa = 0.5;*/ 00148 00149 CubitVector cvRayOrigin(rayOrigin[0], rayOrigin[1], rayOrigin[2]); 00150 CubitVector cvRayDir(pNormal[0], pNormal[1], pNormal[2]); 00151 CubitVector cvPointOnSrfc; 00152 CubitVector closestPointOnSrfc; 00153 00154 // closest point in positive normal direction 00155 RefFace* cgmFacePtr = 00156 dynamic_cast<RefFace*>(reinterpret_cast<RefEntity*>(surface)); 00157 Surface* cgmSrfcPtr = cgmFacePtr->get_surface_ptr(); 00158 CubitStatus posDirResult = cgmSrfcPtr->closest_point_along_vector( 00159 cvRayOrigin, cvRayDir, cvPointOnSrfc); 00160 if (posDirResult == CUBIT_SUCCESS) 00161 { 00162 closestPointOnSrfc = cvPointOnSrfc; 00163 } 00164 00165 cvRayDir *= -1; 00166 CubitStatus negDirResult = cgmSrfcPtr->closest_point_along_vector( 00167 cvRayOrigin, cvRayDir, cvPointOnSrfc); 00168 if (negDirResult == CUBIT_SUCCESS) 00169 { 00170 if (posDirResult == CUBIT_SUCCESS) 00171 { 00172 // REMARK: It might be better to measure the distance in 00173 // parametric coordinates from some source point . . . 00174 00175 // compute square distance to point in positive direction 00176 double posXDiff = closestPointOnSrfc.x() - rayOrigin[0]; 00177 double posYDiff = closestPointOnSrfc.y() - rayOrigin[1]; 00178 double posZDiff = closestPointOnSrfc.z() - rayOrigin[2]; 00179 double posSqDist = posXDiff * posXDiff + 00180 posYDiff * posYDiff + posZDiff * posZDiff; 00181 00182 // compute square distance to point in negative direction 00183 double negXDiff = cvPointOnSrfc.x() - rayOrigin[0]; 00184 double negYDiff = cvPointOnSrfc.y() - rayOrigin[1]; 00185 double negZDiff = cvPointOnSrfc.z() - rayOrigin[2]; 00186 double negSqDist = negXDiff * negXDiff + 00187 negYDiff * negYDiff + negZDiff * negZDiff; 00188 00189 if (negSqDist < posSqDist) 00190 { 00191 closestPointOnSrfc = cvPointOnSrfc; 00192 } 00193 } 00194 else 00195 { 00196 closestPointOnSrfc = cvPointOnSrfc; 00197 } 00198 } 00199 00200 return new AF2Point3D(pntId, closestPointOnSrfc.x(), 00201 closestPointOnSrfc.y(), closestPointOnSrfc.z()); 00202 }