cgma
|
#include <iostream>
#include <map>
#include <cfloat>
#include <cassert>
#include "MCNPInput.hpp"
#include "volumes.hpp"
#include "geometry.hpp"
#include "options.hpp"
Go to the source code of this file.
iBase_EntityHandle applyReverseTransform | ( | const Transform & | tx, |
iGeom_Instance & | igm, | ||
iBase_EntityHandle & | e | ||
) |
Definition at line 93 of file volumes.cpp.
{ int igm_result; Transform rev_t = tx.reverse(); const Vector3d& translation = rev_t.getTranslation(); iGeom_moveEnt( igm, e, translation.v[0], translation.v[1], translation.v[2], &igm_result); CHECK_IGEOM( igm_result, "applying reverse translation" ); if( rev_t.hasInversion() ){ iGeom_rotateEnt( igm, e, 180, 0, 0, 0, &igm_result ); CHECK_IGEOM( igm_result, "inverting for reverse transformation" ); } if( rev_t.hasRot() ){ const Vector3d& axis = rev_t.getAxis(); iGeom_rotateEnt( igm, e, rev_t.getTheta(), axis.v[0], axis.v[1], axis.v[2], &igm_result ); CHECK_IGEOM( igm_result, "applying rotation" ); } return e; }
iBase_EntityHandle applyTransform | ( | const Transform & | t, |
iGeom_Instance & | igm, | ||
iBase_EntityHandle & | e | ||
) |
Definition at line 59 of file volumes.cpp.
{ int igm_result; if( t.hasRot() ){ const Vector3d& axis = t.getAxis(); iGeom_rotateEnt( igm, e, t.getTheta(), axis.v[0], axis.v[1], axis.v[2], &igm_result ); CHECK_IGEOM( igm_result, "applying rotation" ); } if( t.hasInversion() ){ //TODO: ask about the right way to do this. Rotate seems to work, but I don't really know why... //iGeom_rotateEnt( igm, e, 180, 0, 0, 0, &igm_result ); //if( !t.hasRot() ){ iGeom_reflectEnt( igm, e, 0, 0, 0, 0, 0, 1, &igm_result ); iGeom_reflectEnt( igm, e, 0, 0, 0, 0, 1, 0, &igm_result ); iGeom_reflectEnt( igm, e, 0, 0, 0, 1, 0, 0, &igm_result ); //} //else{ // const Vector3d& axis = t.getAxis(); // iGeom_reflectEnt( igm, e, axis.v[0], axis.v[1], axis.v[2], &igm_result ); // } CHECK_IGEOM( igm_result, "inverting for transformation" ); } const Vector3d& translation = t.getTranslation(); iGeom_moveEnt( igm, e, translation.v[0], translation.v[1], translation.v[2], &igm_result); CHECK_IGEOM( igm_result, "applying translation" ); return e; }
static Transform axesImage | ( | const Vector3d & | v1, |
const Vector3d & | v2, | ||
const Vector3d & | v3, | ||
const Vector3d & | translation = Vector3d() |
||
) | [static] |
Definition at line 463 of file volumes.cpp.
{ Vector3d x(1, 0, 0), y(0, 1, 0), z(0, 0, 1); Vector3d a1 = v1.normalize(), a2 = v2.normalize(), a3 = v3.normalize(); if( OPT_DEBUG ) std::cout << "Axes image: " << a1 << " : " << a2 << " : " << a3 << std::endl; double rot_matrix[9] = { a1.dot(x), a2.dot(x), a3.dot(x), a1.dot(y), a2.dot(y), a3.dot(y), a1.dot(z), a2.dot(z), a3.dot(z) }; return Transform( rot_matrix, translation ); }
static iBase_EntityHandle embedWithinWorld | ( | bool | positive, |
iGeom_Instance & | igm, | ||
double | world_size, | ||
iBase_EntityHandle | body, | ||
bool | bound_with_world | ||
) | [static] |
A convenience function for SurfaceVolumes to call at the end of getHandle functions. Return the negative or positive sense of the given body, as appropriate. If bound_within_world is true, a negative-sense body will be intersected with the world sphere (a step necessary for cylinders and other infinite bodies)
Definition at line 33 of file volumes.cpp.
{ iBase_EntityHandle final_body; int igm_result; if( !positive && !bound_with_world ){ final_body = body; } else{ iBase_EntityHandle world_sphere = makeWorldSphere( igm, world_size ); if( positive ){ iGeom_subtractEnts( igm, world_sphere, body, &final_body, &igm_result); CHECK_IGEOM( igm_result, "making positive body" ); } else{ // !positive && bound_with_world iGeom_intersectEnts( igm, world_sphere, body, &final_body, &igm_result); CHECK_IGEOM( igm_result, "making negative body" ); } } return final_body; }
static Transform imageZAxisTo | ( | const Vector3d & | v, |
const Vector3d & | translation = Vector3d() |
||
) | [static] |
Definition at line 479 of file volumes.cpp.
{ // approach: find two vectors perpendicular to v, then use axesImage. Vector3d a = v.normalize(); Vector3d x(1, 0, 0); Vector3d b = x.cross( v.normalize() ); if( b.length() < DBL_EPSILON ){ // v is indistinguishable from the x axis b = Vector3d(0, -1, 0); if( OPT_DEBUG ) std::cout << "imageZAxisTo: Changing v " << std::endl; } Vector3d c = b.cross( v.normalize() ); return axesImage( c, b, a, translation ); }
SurfaceVolume& makeSurface | ( | const SurfaceCard * | card, |
VolumeCache * | v = NULL |
||
) |
Function to create an SurfaceVolume object from a SurfaceCard. Created volumes are kept in a cache. If the v parameter is null, a default cache (static within volumes.cpp) will be used. If multiple MCNPInput instances are used in the course of a single program, then there will need to be a way to get multiple VolumeCache objects; that's not an issue right now, so I haven't coded it.
Definition at line 802 of file volumes.cpp.
{ VolumeCache& cache = default_volume_cache; if( v != NULL ){ cache = *v; } if( cache.contains( card ) ){ return *cache.get( card ); } else{ // SurfaceCard variables: mnemonic, args, coord_xform SurfaceVolume* surface; const std::string& mnemonic = card->getMnemonic(); const std::vector< double >& args = card->getArgs(); if( mnemonic == "so"){ surface = new SphereSurface( origin, args.at(0) ); } else if( mnemonic == "sx"){ surface = new SphereSurface( Vector3d( args.at(0), 0, 0 ), args.at(1) ); } else if( mnemonic == "sy"){ surface = new SphereSurface( Vector3d( 0, args.at(0), 0 ), args.at(1) ); } else if( mnemonic == "sz"){ surface = new SphereSurface( Vector3d( 0, 0, args.at(0) ), args.at(1) ); } else if( mnemonic == "s" || mnemonic == "sph" ){ surface = new SphereSurface( Vector3d( args ), args.at(3) ); } else if( mnemonic == "sq" && sqIsEllipsoid(args) ){ surface = new EllipsoidSurface( Vector3d( args.at(7), args.at(8), args.at(9) ), Vector3d( args )* (-1/args.at(6)) ); } else if( mnemonic == "p"){ if( args.size() == 4 ){ // plane given as ABCD coefficients (Ax+By+Cz-D=0) Vector3d v(args); surface = new PlaneSurface( v, args.at(3)/v.length() ); } else if( args.size() == 9 ){ // plane is given at three points in space Vector3d v1(args), v2(args,3), v3(args,6); // ordering of the points is arbitrary, but make sure v1 is furthest from origin. if( v1.length() < v2.length() ){ std::swap( v1, v2 ); } if( v1.length() < v3.length() ){ std::swap( v1, v3 ); } // the normal (up to reversal) of the plane // The normal may need to be reversed to ensure that the origin // has negative sense, as required by MCNP Vector3d normal = v1.add(-v2).cross( v1.add(-v3) ).normalize(); // If a ray started from the origin and followed the normal vector, // p is the point where it intersects the plane Vector3d p = normal.scale( v1.dot(normal) ); // cos of the angle between v1 and normal double angle = normal.dot( v1.normalize() ); // invert the normal if the angle is > 90 degrees, which indicates // that reversal is required. if( angle < 0 ){ normal = -normal; } //std::cout << normal << " " << p.length() << " : " << angle << std::endl; surface = new PlaneSurface( normal, p.length() ); } else{ throw std::runtime_error( "P surface with unsupported number of params" ); } } else if( mnemonic == "px"){ surface = new PlaneSurface( Vector3d( 1, 0, 0), args.at(0) ); } else if( mnemonic == "py"){ surface = new PlaneSurface( Vector3d( 0, 1, 0), args.at(0) ); } else if( mnemonic == "pz"){ surface = new PlaneSurface( Vector3d( 0, 0, 1), args.at(0) ); } else if( mnemonic == "cx" ){ surface = new CylinderSurface( X, args.at(0) ); } else if( mnemonic == "cy" ){ surface = new CylinderSurface( Y, args.at(0) ); } else if( mnemonic == "cz" ){ surface = new CylinderSurface( Z, args.at(0) ); } else if( mnemonic == "c/x"){ surface = new CylinderSurface( X, args.at(2), args.at(0), args.at(1) ); } else if( mnemonic == "c/y"){ surface = new CylinderSurface( Y, args.at(2), args.at(0), args.at(1) ); } else if( mnemonic == "c/z"){ surface = new CylinderSurface( Z, args.at(2), args.at(0), args.at(1) ); } #ifdef HAVE_IGEOM_CONE else if( mnemonic == "kx"){ double arg3 = ( args.size() == 3 ? args.at(2) : 0.0 ); surface = new ConeSurface( X, args.at(1), args.at(0), arg3 ); } else if( mnemonic == "ky"){ double arg3 = ( args.size() == 3 ? args.at(2) : 0.0 ); surface = new ConeSurface( Y, args.at(1), args.at(0), arg3 ); } else if( mnemonic == "kz"){ double arg3 = ( args.size() == 3 ? args.at(2) : 0.0 ); surface = new ConeSurface( Z, args.at(1), args.at(0), arg3 ); } else if( mnemonic == "k/x" ){ double arg5 = ( args.size() == 5 ? args.at(4) : 0.0 ); surface = new ConeSurface( X, args.at(3), Vector3d(args), arg5 ); } else if( mnemonic == "k/y" ){ double arg5 = ( args.size() == 5 ? args.at(4) : 0.0 ); surface = new ConeSurface( Y, args.at(3), Vector3d(args), arg5 ); } else if( mnemonic == "k/z" ){ double arg5 = ( args.size() == 5 ? args.at(4) : 0.0 ); surface = new ConeSurface( Z, args.at(3), Vector3d(args), arg5 ); } else if( mnemonic == "trc" ){ surface = new TrcVolume( Vector3d(args), Vector3d(args,3), args.at(6), args.at(7) ); } #endif /*HAVE_IGEOM_CONE */ else if( mnemonic == "tx" ){ surface = new TorusSurface( X, Vector3d(args), args.at(3), args.at(4), args.at(5) ); } else if( mnemonic == "ty" ){ surface = new TorusSurface( Y, Vector3d(args), args.at(3), args.at(4), args.at(5) ); } else if( mnemonic == "tz" ){ surface = new TorusSurface( Z, Vector3d(args), args.at(3), args.at(4), args.at(5) ); } else if( mnemonic == "box" ){ surface = new BoxVolume( Vector3d(args), Vector3d(args,3), Vector3d(args,6), Vector3d(args,9) ); } else if( mnemonic == "rpp" ){ surface = new RppVolume( Vector3d(args.at(0), args.at(2), args.at(4)), Vector3d(args.at(1), args.at(3), args.at(5)) ); } else if( mnemonic == "rcc" ){ surface = new RccVolume( Vector3d(args), Vector3d(args,3), args.at(6) ); } else if( mnemonic == "rec" ){ if( args.size() == 10 ){ surface = new RecVolume( Vector3d( args ), Vector3d(args,3), Vector3d(args,6), args.at(9) ); } else{ surface = new RecVolume( Vector3d( args ), Vector3d(args,3), Vector3d(args,6), Vector3d(args,9) ); } } else if( mnemonic == "hex" || mnemonic == "rhp" ){ if( args.size() == 9 ){ surface = new HexVolume( Vector3d( args ), Vector3d(args,3), Vector3d(args,6) ); } else{ surface = new HexVolume( Vector3d( args ), Vector3d(args,3), Vector3d(args,6), Vector3d(args,9), Vector3d(args,12) ); } } else if( mnemonic == "x" ) { switch (args.size()) { case 2: // plane surface = new PlaneSurface( Vector3d( 1, 0, 0), args.at(0) ); break; case 4: // either plane, cylinder or cone if ( args.at(0) == args.at(2) ) // plane surface = new PlaneSurface( Vector3d( 1, 0, 0), args.at(0) ); else if (args.at(1) == args.at(3)) // cylinder surface = new CylinderSurface( X, args.at(1) ); else // cone { double m = (args.at(3) - args.at(1))/(args.at(2)-args.at(0)); double apex_p = args.at(0) - args.at(1)/m; surface = new ConeSurface( X, m*m, apex_p, (m > 0 ? 1 : -1 ) ); } break; default: throw std::runtime_error( mnemonic + " is only a supported surface with 2 or 4 arguments" ); break; } } else if( mnemonic == "y" ) { switch (args.size()) { case 2: // plane surface = new PlaneSurface( Vector3d( 0, 1, 0), args.at(0) ); break; case 4: // either plane, cylinder or cone if ( args.at(0) == args.at(2) ) // plane surface = new PlaneSurface( Vector3d( 0, 1, 0), args.at(0) ); else if (args.at(1) == args.at(3)) // cylinder surface = new CylinderSurface( Y, args.at(1) ); else // cone { double m = (args.at(3) - args.at(1))/(args.at(2)-args.at(0)); double apex_p = args.at(0) - args.at(1)/m; surface = new ConeSurface( Y, m*m, apex_p, (m > 0 ? 1 : -1 ) ); } break; default: throw std::runtime_error( mnemonic + " is only a supported surface with 2 or 4 arguments" ); break; } } else if( mnemonic == "z" ) { switch (args.size()) { case 2: // plane surface = new PlaneSurface( Vector3d( 0, 0, 1), args.at(0) ); break; case 4: // either plane, cylinder or cone if ( args.at(0) == args.at(2) ) // plane surface = new PlaneSurface( Vector3d( 0, 0, 1), args.at(0) ); else if (args.at(1) == args.at(3)) // cylinder surface = new CylinderSurface( Z, args.at(1) ); else // cone { double m = (args.at(3) - args.at(1))/(args.at(2)-args.at(0)); double apex_p = args.at(0) - args.at(1)/m; surface = new ConeSurface( Z, m*m, apex_p, (m > 0 ? 1 : -1 ) ); } break; default: throw std::runtime_error( mnemonic + " is only a supported surface with 2 or 4 arguments" ); break; } } else{ throw std::runtime_error( mnemonic + " is not a supported surface" ); } if( card->getTransform().hasData() ){ const Transform& transform = card->getTransform().getData(); surface->setTransform( &transform ); } cache.insert( card, surface ); return *surface; } }
iBase_EntityHandle makeWorldSphere | ( | iGeom_Instance & | igm, |
double | world_size | ||
) |
Definition at line 16 of file volumes.cpp.
{ iBase_EntityHandle world_sphere; int igm_result; // Note: I tried using createBrick instead of createSphere to bound the universe with a box // instead of a sphere. This worked but led to a substantial increase in run times and // memory usage, so should be avoided. iGeom_createSphere( igm, world_size, &world_sphere, &igm_result); CHECK_IGEOM( igm_result, "making world sphere" ); return world_sphere; }
bool sqIsEllipsoid | ( | const std::vector< double > & | args | ) |
Definition at line 785 of file volumes.cpp.
{ bool isEllipsoid = true; if ( args.at(3)*args.at(3) + args.at(4)*args.at(4) + args.at(5)*args.at(5) != 0) isEllipsoid = false; if ( args.at(0)*args.at(1)*args.at(2)*args.at(6) >= 0 ) isEllipsoid = false; return isEllipsoid; }
VolumeCache default_volume_cache [static] |
Definition at line 800 of file volumes.cpp.