CMS 3D CMS Logo

IgSoFieldPlane.cc

Go to the documentation of this file.
00001 //<<<<<< INCLUDES                                                       >>>>>>
00002 
00003 #include "Iguana/Inventor/interface/IgSoFieldPlane.h"
00004 #include "Iguana/Inventor/interface/IgSoFieldPlaneMap.h"
00005 #include "Iguana/Inventor/interface/IgSbColorMap.h"
00006 #include "Iguana/Inventor/interface/IgSbField.h"
00007 #include "Iguana/Inventor/interface/IgSoPlaneManip.h"
00008 #include <Inventor/nodes/SoText2.h>
00009 #include <Inventor/nodes/SoTranslation.h>
00010 #include <Inventor/nodes/SoResetTransform.h>
00011 #include <Inventor/nodes/SoIndexedLineSet.h>
00012 #include <Inventor/nodes/SoVertexProperty.h>
00013 #include <Inventor/sensors/SoFieldSensor.h>
00014 #include <Inventor/SbLinear.h>
00015 //#include <SealBase/DebugAids.h>
00016 #include <math.h>
00017 #include <assert.h>
00018 
00019 #ifdef WIN32
00020 # include <windows.h>
00021 #endif
00022 #ifdef __APPLE__
00023 # include <OpenGL/gl.h>                                                                        
00024 #else
00025 # include <GL/gl.h>
00026 #endif
00027 
00028 //<<<<<< PRIVATE DEFINES                                                >>>>>>
00029 
00030 #define MINIMUM(a,b) ((a)<(b)?a:b)
00031 #define MAXIMUM(a,b) ((a)>(b)?a:b)
00032 
00033 //<<<<<< PRIVATE CONSTANTS                                              >>>>>>
00034 //<<<<<< PRIVATE TYPES                                                  >>>>>>
00035 //<<<<<< PRIVATE VARIABLE DEFINITIONS                                   >>>>>>
00036 //<<<<<< PUBLIC VARIABLE DEFINITIONS                                    >>>>>>
00037 //<<<<<< CLASS STRUCTURE INITIALIZATION                                 >>>>>>
00038 
00039 SO_NODE_SOURCE (IgSoFieldPlane);
00040 
00041 //<<<<<< PRIVATE FUNCTION DEFINITIONS                                   >>>>>>
00042 //<<<<<< PUBLIC FUNCTION DEFINITIONS                                    >>>>>>
00043 //<<<<<< MEMBER FUNCTION DEFINITIONS                                    >>>>>>
00044 
00045 void
00046 IgSoFieldPlane::initClass (void)
00047 {
00048     SO_NODE_INIT_CLASS (IgSoFieldPlane, SoSwitch, "Switch");
00049 }
00050 
00051 IgSoFieldPlane::IgSoFieldPlane (void)
00052     : m_cmap (IgSbColorMap::getColorMap (IgSbColorMap::Jet)),
00053       m_field (0),
00054       m_manip (0),
00055       m_fieldPlane (0),
00056       m_segments (0),
00057       m_gradientScale (0),
00058       m_showSensor (0),
00059       m_planeSensor (0),
00060       m_mapDensityXSensor (0),
00061       m_mapDensityZSensor (0),
00062       m_segRatioXSensor (0),
00063       m_segRatioZSensor (0),
00064       m_winSizeXSensor (0),
00065       m_winSizeZSensor (0),
00066       m_winDensityXSensor (0),
00067       m_winDensityZSensor (0),
00068       m_winOriginXSensor (0),
00069       m_winOriginZSensor (0),
00070       m_componentSensor (0),
00071       m_maxvalueSensor (0),
00072       m_invisibleSensor (0),
00073       m_alphaSensor (0),
00074       m_mplaneSensor (0),
00075       m_gradientScaleSensor (0)
00076 {
00077         SO_NODE_CONSTRUCTOR (IgSoFieldPlane);
00078         SO_NODE_ADD_FIELD (plane, (SbPlane (SbVec3f (0.0f, 1.0f, 0.0f), 00.f)));
00079         SO_NODE_ADD_FIELD (mapDensityX, (50));
00080         SO_NODE_ADD_FIELD (mapDensityZ, (50));
00081         SO_NODE_ADD_FIELD (segRatioX, (2));
00082         SO_NODE_ADD_FIELD (segRatioZ, (2));
00083         
00084         SO_NODE_ADD_FIELD (winSizeX, (10.0f));
00085         SO_NODE_ADD_FIELD (winSizeZ, (10.0f));
00086         SO_NODE_ADD_FIELD (winDensityX, (2));
00087         SO_NODE_ADD_FIELD (winDensityZ, (2));
00088         SO_NODE_ADD_FIELD (winOriginX, (0.0f));
00089         SO_NODE_ADD_FIELD (winOriginZ, (0.0f));
00090         
00091         SO_NODE_ADD_FIELD (component, (XYZ_ALL));
00092         SO_NODE_DEFINE_ENUM_VALUE (Component, XYZ_ALL);
00093         SO_NODE_DEFINE_ENUM_VALUE (Component, XYZ_X);
00094         SO_NODE_DEFINE_ENUM_VALUE (Component, XYZ_Y);
00095         SO_NODE_DEFINE_ENUM_VALUE (Component, XYZ_Z);
00096         SO_NODE_DEFINE_ENUM_VALUE (Component, XYZ_R);
00097         SO_NODE_DEFINE_ENUM_VALUE (Component, XYZ_PHI);
00098         SO_NODE_SET_SF_ENUM_TYPE (component, Component);        
00099         SO_NODE_ADD_FIELD (maxvalue, (4.75f));
00100         SO_NODE_ADD_FIELD (invisible, (0));
00101         SO_NODE_ADD_FIELD (alpha, (255));
00102         SO_NODE_ADD_FIELD (show, (FALSE));
00103         SO_NODE_ADD_FIELD (manip, (FALSE));
00104         SO_NODE_ADD_FIELD (showMap, (TRUE));
00105         SO_NODE_ADD_FIELD (showSegments, (TRUE));
00106         SO_NODE_ADD_FIELD (gradientScale, (TRUE));
00107 
00108         // SO_NODE_ADD_FIELD (showContours, (TRUE));
00109         // SO_NODE_ADD_FIELD (showSurfaces, (TRUE));
00110         
00111         // Add callbacks to determine field changes
00112         m_showSensor          = new SoFieldSensor (&showChanged, this);
00113         m_showMapSensor       = new SoFieldSensor (&showMapChanged, this);
00114         m_showSegmentsSensor  = new SoFieldSensor (&showSegmentsChanged, this);
00115         m_gradientScaleSensor = new SoFieldSensor (&gradientScaleChanged, this);
00116         
00117         m_showSensor->attach (&show);
00118         m_showMapSensor->attach (&showMap);
00119         m_showSegmentsSensor->attach (&showSegments);
00120         m_gradientScaleSensor->attach (&gradientScale);
00121 }
00122 
00123 IgSoFieldPlane::~IgSoFieldPlane (void)
00124 {
00125         show = FALSE;
00126         showMap = FALSE;
00127         showSegments = FALSE;
00128         gradientScale = FALSE;
00129         
00130         if (m_fieldPlane)
00131         {
00132                 m_fieldPlane->unref ();
00133                 m_segments->unref ();
00134                 m_gradientScale->unref ();
00135         }
00136         
00137         if (m_planeSensor)
00138         {
00139                 delete m_planeSensor;
00140                 delete m_mplaneSensor;
00141                 delete m_mapDensityXSensor;
00142                 delete m_mapDensityZSensor;
00143                 delete m_segRatioXSensor;
00144                 delete m_segRatioZSensor;
00145                 
00146                 delete m_winSizeXSensor;
00147                 delete m_winSizeZSensor;
00148                 delete m_winDensityXSensor;
00149                 delete m_winDensityZSensor;
00150                 delete m_winOriginXSensor;
00151                 delete m_winOriginZSensor;
00152                 
00153                 delete m_componentSensor;
00154                 delete m_maxvalueSensor;
00155                 delete m_invisibleSensor;
00156                 delete m_alphaSensor;
00157         }
00158         
00159         delete m_showSensor;
00160         delete m_showMapSensor;
00161         delete m_showSegmentsSensor;
00162         delete m_gradientScaleSensor;
00163 }
00164 
00165 void
00166 IgSoFieldPlane::colorMap (const IgSbColorMap *cmap)
00167 {
00168         assert (cmap);
00169         m_cmap = cmap;
00170         if (show.getValue () && m_field)
00171         {
00172                 refreshColors ();
00173         }
00174 }
00175 
00176 void
00177 IgSoFieldPlane::attachSensors (void)
00178 {
00179         m_planeSensor->attach (&plane);
00180         m_mapDensityXSensor->attach (&mapDensityX);
00181         m_mapDensityZSensor->attach (&mapDensityZ);
00182         m_segRatioXSensor->attach (&segRatioX);
00183         m_segRatioZSensor->attach (&segRatioZ);
00184         
00185         m_winSizeXSensor->attach (&winSizeX);
00186         m_winSizeZSensor->attach (&winSizeZ);
00187         m_winDensityXSensor->attach (&winDensityX);
00188         m_winDensityZSensor->attach (&winDensityZ);
00189         m_winOriginXSensor->attach (&winOriginX);
00190         m_winOriginZSensor->attach (&winOriginZ);
00191         
00192         m_componentSensor->attach (&component);
00193         m_maxvalueSensor->attach (&maxvalue);
00194         m_invisibleSensor->attach (&invisible);
00195         m_alphaSensor->attach (&alpha);
00196         m_mplaneSensor->attach (&m_manip->plane);
00197 }
00198 
00199 void
00200 IgSoFieldPlane::detachSensors (void)
00201 {
00202         m_planeSensor->detach ();
00203         m_mapDensityXSensor->detach ();
00204         m_mapDensityZSensor->detach ();
00205         m_segRatioXSensor->detach ();
00206         m_segRatioZSensor->detach ();
00207         
00208         m_winSizeXSensor->detach ();
00209         m_winSizeZSensor->detach ();
00210         m_winDensityXSensor->detach ();
00211         m_winDensityZSensor->detach ();
00212         m_winOriginXSensor->detach ();
00213         m_winOriginZSensor->detach ();
00214         
00215         m_componentSensor->detach ();
00216         m_maxvalueSensor->detach ();
00217         m_invisibleSensor->detach ();
00218         m_alphaSensor->detach ();
00219         m_mplaneSensor->detach ();
00220 }
00221 
00222 
00223 void
00224 IgSoFieldPlane::field (const IgSbField *field, SbBox3f world)
00225 {
00226         // FIXME: Replace world by a SbBox. for example viewingbox?
00227         m_world = world;
00228 
00229         if (field)
00230         {
00231                 buildStructure ();
00232         
00233                 if (!m_planeSensor)
00234                 {
00235                         // Add callbacks to determine field plane changes
00236                         m_planeSensor  = new SoFieldSensor (&planeChanged, this);
00237                         m_mplaneSensor = new SoFieldSensor (&mplaneChanged, this);
00238                 
00239                         //Update segments and colour map when these field are changed
00240                         m_mapDensityXSensor =
00241                                 new SoFieldSensor (&resampleSegmentsCB, this);
00242                         m_mapDensityZSensor = 
00243                                 new SoFieldSensor (&resampleSegmentsCB, this);
00244                         m_componentSensor   = 
00245                                 new SoFieldSensor (&resampleSegmentsCB, this);
00246                         m_maxvalueSensor    = 
00247                                 new SoFieldSensor (&resampleSegmentsCB, this);
00248                         m_invisibleSensor   = 
00249                                 new SoFieldSensor (&resampleSegmentsCB, this);
00250                         m_alphaSensor       = 
00251                                 new SoFieldSensor (&resampleSegmentsCB, this);
00252                         m_segRatioXSensor   = 
00253                                 new SoFieldSensor (&resampleSegmentsCB, this);
00254                         m_segRatioZSensor   = 
00255                                 new SoFieldSensor (&resampleSegmentsCB, this);
00256                         m_winSizeXSensor    =
00257                                 new SoFieldSensor (&resampleSegmentsCB, this);
00258                         m_winSizeZSensor    =
00259                                 new SoFieldSensor (&resampleSegmentsCB, this);
00260                         m_winDensityXSensor =
00261                                 new SoFieldSensor (&resampleSegmentsCB, this);
00262                         m_winDensityZSensor =
00263                                 new SoFieldSensor (&resampleSegmentsCB, this);
00264                         m_winOriginXSensor  =
00265                                 new SoFieldSensor (&resampleSegmentsCB, this);
00266                         m_winOriginZSensor  =
00267                                 new SoFieldSensor (&resampleSegmentsCB, this);
00268                 }
00269                 else if (m_field)
00270                 {
00271                         detachSensors ();
00272                 }
00273 
00274                 if (!m_field)
00275                 {
00276                         m_manip->manip.connectFrom (&manip);
00277                         //m_fieldPlane->xdivs.connectFrom (&mapDensityX);
00278                         //m_fieldPlane->zdivs.connectFrom (&mapDensityZ);
00279                 }       
00280                 m_field = field;
00281                 update ();
00282                 attachSensors ();
00283                 m_showSensor->attach (&show);
00284                 m_showMapSensor->attach (&showMap);
00285                 m_showSegmentsSensor->attach (&showSegments);
00286                 m_gradientScaleSensor->attach (&gradientScale);
00287                 show = TRUE;
00288         }
00289         else if (m_field)
00290         {
00291                 m_field = field;
00292                 manip = FALSE;
00293                 show = FALSE;
00294                 showMap = FALSE;
00295                 showSegments = FALSE;
00296                 gradientScale = FALSE;
00297                 m_manip->manip.disconnect ();
00298                 //m_fieldPlane->xdivs.disconnect ();
00299                 //m_fieldPlane->zdivs.disconnect ();
00300                 m_showSensor->detach ();
00301                 m_showMapSensor->detach ();
00302                 m_showSegmentsSensor->detach ();
00303                 m_gradientScaleSensor->detach ();
00304                 detachSensors ();
00305         }
00306 }
00307 
00308 void
00309 IgSoFieldPlane::buildStructure (void)
00310 {
00311         if (m_manip) {return;}
00312         
00313         assert ((getNumChildren () == 0) || (getNumChildren () >= 2));
00314         
00315         if (getNumChildren () == 0)
00316         {
00317                 whichChild = SO_SWITCH_NONE;
00318         
00319                 // Kill the transform, all the rest is in world coordinates
00320                 addChild (new SoResetTransform);
00321         
00322                 // Add the plane manipulator
00323                 m_manip = new IgSoPlaneManip;
00324                 addChild (m_manip);
00325         }
00326         else
00327         {
00328                 m_manip = dynamic_cast<IgSoPlaneManip*>(getChild(1));
00329         
00330                 assert (dynamic_cast<SoResetTransform*>(getChild(0)));
00331                 assert (m_manip);
00332         
00333                 if (m_manip->manip.isConnectedFromField ())
00334                 {
00335                         m_manip->manip.disconnect ();
00336                 }
00337                 m_manip->manip = FALSE;
00338 
00339                 for(int i = 2; i < getNumChildren (); i++)
00340                 {
00341                         SoNode *child = getChild(i);
00342                         if (!m_fieldPlane && dynamic_cast<IgSoFieldPlaneMap*>(child)
00343                                 && child->getName() == SbName ("FieldMap"))
00344                         {
00345                                 m_fieldPlane = dynamic_cast<IgSoFieldPlaneMap*>(child);
00346                         }
00347                         else if (!m_segments && dynamic_cast<SoIndexedLineSet*>(child))
00348                         {
00349                                 m_segments = dynamic_cast<SoIndexedLineSet*>(child);
00350                         }
00351                         else if (!m_gradientScale && dynamic_cast<SoGroup*>(child)
00352                                                 && child->getName() == SbName ("GradientScale"))
00353                         {
00354                                 m_gradientScale = dynamic_cast<SoGroup*>(child);
00355                                 assert (m_gradientScale->getNumChildren () == 12);
00356                         }
00357                         if (m_fieldPlane && m_segments && m_gradientScale)
00358                         {
00359                                 break;
00360                         }
00361                 }
00362         }       
00363     
00364         if (!m_segments)
00365         {
00366                 m_segments = new SoIndexedLineSet;
00367                 SoVertexProperty *vtx = new SoVertexProperty;
00368                 vtx->orderedRGBA = 0xff0000ff;
00369                 vtx->materialBinding = SoVertexProperty::OVERALL;
00370                 m_segments->vertexProperty = vtx;
00371                 
00372                 if (showSegments.getValue ())
00373                 {
00374                         addChild (m_segments);
00375                 }
00376         }
00377 
00378         if (!m_fieldPlane)
00379         {
00380                 m_fieldPlane = new IgSoFieldPlaneMap;
00381                 m_fieldPlane->setName ("FieldMap");
00382                 if (showMap.getValue ())
00383                 {
00384                         addChild (m_fieldPlane);
00385                 }
00386         }
00387         else
00388         {
00389                 //m_fieldPlane->xdivs.disconnect ();
00390                 //m_fieldPlane->zdivs.disconnect ();
00391         }
00392     
00393         if (!m_gradientScale)
00394         {
00395                 m_gradientScale = new SoGroup;
00396                 m_gradientScale->setName ("GradientScale");
00397                 IgSoFieldPlaneMap *gs = new IgSoFieldPlaneMap;
00398 //              gs->xdivs = 10;
00399 //              gs->zdivs = 1;
00400                 m_gradientScale->addChild (gs);
00401                 
00402                 SoIndexedLineSet *grid = new SoIndexedLineSet;
00403                 SoVertexProperty *vtx = new SoVertexProperty;
00404                 vtx->orderedRGBA = 0xffffffff;
00405                 vtx->materialBinding = SoVertexProperty::OVERALL;
00406                 grid->vertexProperty = vtx;
00407                 m_gradientScale->addChild (grid);
00408                         
00409                 m_gradientScale->addChild (new SoTranslation);
00410                 m_gradientScale->addChild (new SoText2);
00411                 m_gradientScale->addChild (new SoTranslation);
00412                 m_gradientScale->addChild (new SoText2);
00413                 m_gradientScale->addChild (new SoTranslation);
00414                 m_gradientScale->addChild (new SoText2);
00415                 m_gradientScale->addChild (new SoTranslation);
00416                 m_gradientScale->addChild (new SoText2);
00417                 m_gradientScale->addChild (new SoTranslation);
00418                 m_gradientScale->addChild (new SoText2);
00419                 if (gradientScale.getValue ())
00420                 {       
00421                         addChild (m_gradientScale);
00422                 }
00423         }
00424         
00425         m_segments->ref ();
00426         m_fieldPlane->ref ();
00427         m_gradientScale->ref ();
00428 }
00429 
00430 void
00431 IgSoFieldPlane::update (void)
00432 {
00433         // update the interscetion 
00434         updateCorners ();
00435         
00436         //resample the segments and colors
00437         resampleSegments ();
00438 }
00439 
00440 void
00441 IgSoFieldPlane::updateCorners (void)
00442 {
00443     // Determine the minimum rectangular intersection of the field's
00444     // volume bounding box and our slice plane.  Sample the field
00445     // within this minimal rectangle.  The plane is thought to be in
00446     // in X-Z space with Y axis as the plane normal, but all this is
00447     // transformed by `matrix'.
00448 
00449     SbMatrix matrix;
00450     m_manip->getMotionMatrix (matrix);
00451 
00452     SbVec3f             xdir   (matrix[0][0],matrix[0][1],matrix[0][2]);
00453     SbVec3f             zdir   (matrix[2][0],matrix[2][1],matrix[2][2]);
00454     SbVec3f             origin (matrix[3][0],matrix[3][1],matrix[3][2]);
00455     SbPlane             slicePlane (plane.getValue ());
00456 
00457     // Calculate the minimal rectangular intersection of the slice
00458     // plane and the sliced volume bounding box as follows.  Check
00459     // which bounding box edges intersect the plane.  For the edges
00460     // that do, track the minimum and maximum coordinates for the
00461     // plane intersection point (X-Z points on the plane, Y being the
00462     // normal).  The minimal rectangle is determined by the minimum
00463     // and maximum X-Z values of such points.  If no edge intersects
00464     // the plane or the rectangle would otherwise be "too small", give
00465     // the rectangle an artificial smallish size.
00466 
00467     int                 nedges = 0;     // # of edges intersecting plane
00468     float               xmin = 0.f;     // min x of intersecting edges
00469     float               xmax = 0.f;     // max x of intersecting edges
00470     float               zmin = 0.f;     // min z of intersecting edges
00471     float               zmax = 0.f;     // max z of intersecting edges
00472     SbVec3f             wcorners [8] = {// world bounding box corners
00473         SbVec3f (m_world.getMin()[0], m_world.getMin()[1], m_world.getMin()[2]),
00474         SbVec3f (m_world.getMin()[0], m_world.getMin()[1], m_world.getMax()[2]),
00475         SbVec3f (m_world.getMin()[0], m_world.getMax()[1], m_world.getMin()[2]),
00476         SbVec3f (m_world.getMin()[0], m_world.getMax()[1], m_world.getMax()[2]),
00477         SbVec3f (m_world.getMax()[0], m_world.getMin()[1], m_world.getMin()[2]),
00478         SbVec3f (m_world.getMax()[0], m_world.getMin()[1], m_world.getMax()[2]),
00479         SbVec3f (m_world.getMax()[0], m_world.getMax()[1], m_world.getMin()[2]),
00480         SbVec3f (m_world.getMax()[0], m_world.getMax()[1], m_world.getMax()[2])
00481     };
00482     static const int    edgeidx [] = {  // edges between vertices in `wcorners'
00483         0, 1,           // (xmin,        ymin,        zmin - zmax)
00484         0, 2,           // (xmin,        ymin - ymax, zmin       )
00485         2, 3,           // (xmin,        ymin,        zmin - zmax)
00486         1, 3,           // (xmin,        ymin - ymax, zmin       )
00487         0, 4,           // (xmin - xmax, ymin,        zmin       )
00488         1, 5,           // (xmin - xmax, ymin,        zmax       )
00489         3, 7,           // (xmin - xmax, ymax,        zmax       )
00490         2, 6,           // (xmin - xmax, ymax,        zmin       )
00491         4, 5,           // (xmax,        ymin,        zmin - zmax)
00492         4, 6,           // (xmax,        ymin - ymax, zmin       )
00493         6, 7,           // (xmax,        ymin,        zmin - zmax)
00494         5, 7,           // (xmax,        ymin - ymax, zmin       )
00495         -1, -1,
00496     };
00497 
00498     for (int i = 0; edgeidx [i] != -1; i += 2)
00499     {
00500         // Define a line along the edge.
00501         SbVec3f pt0 (wcorners [edgeidx [i]]);
00502         SbVec3f pt1 (wcorners [edgeidx [i+1]]);
00503         SbLine  edge (pt0, pt1);
00504         SbVec3f point;
00505         float   product = 0.f;
00506 
00507         // Check if the edge line intersects the plane, and if so, if
00508         // the intersection point is within the edge end points.  If
00509         // so, record min and max plane X-Z points.
00510         if (slicePlane.intersect (edge, point)
00511             && (product = (point - pt0).dot (edge.getDirection ())) >= 0.f
00512             && product <= (pt1 - pt0).length ())
00513         {
00514             float x = xdir.dot (point - origin);
00515             float z = zdir.dot (point - origin);
00516             if (++nedges == 1)
00517             {
00518                 xmin = xmax = x;
00519                 zmin = zmax = z;
00520             }
00521             else
00522             {
00523                 xmin = MINIMUM (xmin, x);
00524                 xmax = MAXIMUM (xmax, x);
00525                 zmin = MINIMUM (zmin, z);
00526                 zmax = MAXIMUM (zmax, z);
00527             }
00528 
00529         }
00530     }
00531 
00532     if (xmax - xmin < 1.f)
00533     {
00534         float xcenter = (xmax + xmin) / 2;
00535         xmin = xcenter - .5f;
00536         xmax = xcenter + .5f;
00537     }
00538 
00539     if (zmax - zmin < 1.f)
00540     {
00541         float zcenter = (zmax + zmin) / 2;
00542         zmin = zcenter - .5f;
00543         zmax = zcenter + .5f;
00544     }
00545 
00546     // OK, now define the plane.  (FIXME: Optimise code here and above
00547     // such that in-plane rotation around the normal is ignored and we
00548     // always sample orthogonal to the bounding box volume; now x/zdir
00549     // may include rotation around plane normal, and it would be best
00550     // to ignore it.  For this to work we need ensure the result is
00551     // still a rectangle, which (and reasonable size thereof) may end
00552     // up being more trouble to figure out than it is worth.)
00553     SbVec3f corners [4];
00554     corners [0] = origin + xmin * xdir + zmin * zdir;
00555     corners [1] = origin + xmax * xdir + zmin * zdir;
00556     corners [2] = origin + xmin * xdir + zmax * zdir;
00557     corners [3] = origin + xmax * xdir + zmax * zdir;
00558     
00559     m_fieldPlane->corners.setValues (0, 4, corners);
00560     
00561     // Gradient Scale map corners
00562     zmax += 0.5f;
00563     corners [0] = corners [2];
00564     corners [1] = corners [3];
00565     corners [2] = origin + xmin * xdir + zmax * zdir;
00566     corners [3] = origin + xmax * xdir + zmax * zdir;
00567 
00568     assert (dynamic_cast<IgSoFieldPlaneMap*>(m_gradientScale->getChild(0)));
00569     assert (dynamic_cast<SoIndexedLineSet*>(m_gradientScale->getChild(1)));
00570     
00571     static_cast<IgSoFieldPlaneMap*>(m_gradientScale->getChild(0))->
00572         corners.setValues (0, 4, corners);
00573 
00574     // Draw the out line and ticks
00575     // First draw the out line of the gradient map
00576     float lineOffset = 0.01;
00577     corners[0][0] -= lineOffset;
00578     corners[0][2] -= lineOffset;
00579     corners[1][0] += lineOffset;
00580     corners[1][2] -= lineOffset;
00581     corners[2][0] -= lineOffset;
00582     corners[2][2] += lineOffset;
00583     corners[3][0] += lineOffset;
00584     corners[3][2] += lineOffset;
00585     
00586     std::vector<int>    coords;
00587     std::vector<SbVec3f> vtxs;
00588     vtxs.push_back (corners [0]);
00589     vtxs.push_back (corners [1]);
00590     vtxs.push_back (corners [3]);
00591     vtxs.push_back (corners [2]);
00592     for(int i = 0; i <= 4; i++)
00593       coords.push_back (i%4);
00594     coords.push_back (SO_END_LINE_INDEX);
00595 
00596     // Now draw the ticks
00597     // Add first tick here
00598     assert (dynamic_cast<SoTranslation*>(m_gradientScale->getChild(2)));
00599     
00600     SoTranslation *t = static_cast<SoTranslation*>(m_gradientScale->
00601                            getChild(2));
00602     t->translation = corners [2];
00603     SbVec3f step = (corners [3]-corners [2])/4;
00604     SbVec3f pcorner = corners [2];
00605     SbVec3f tmpcorner = corners [2];
00606     
00607     tmpcorner[2] += 0.5f;
00608     vtxs.push_back (tmpcorner);
00609     unsigned vsize = vtxs.size ();
00610     coords.push_back (vsize - 2);
00611     coords.push_back (vsize - 1);
00612     coords.push_back (SO_END_LINE_INDEX);
00613     
00614     // Add the rest of 4 ticks here
00615     for (int i = 1; i <= 4; i++)
00616     {
00617                 assert (dynamic_cast<SoTranslation*> (m_gradientScale->getChild ((i * 2) + 2)));
00618                 t = static_cast<SoTranslation*> (m_gradientScale->getChild ((i * 2) + 2));
00619                 t->translation = step;
00620                 pcorner = pcorner + step;
00621                 vtxs.push_back (pcorner);
00622                 tmpcorner = pcorner;
00623                 tmpcorner[2] += 0.5f;
00624                 vtxs.push_back (tmpcorner);
00625                 vsize = vtxs.size ();
00626                 coords.push_back (vsize - 2);
00627                 coords.push_back (vsize - 1);
00628                 coords.push_back (SO_END_LINE_INDEX);
00629     }
00630     
00631     SoIndexedLineSet *grid = static_cast<SoIndexedLineSet*>(m_gradientScale->getChild(1));
00632     SoVertexProperty *vtx = (SoVertexProperty *)grid->vertexProperty.getValue ();
00633     vtx->vertex.setValues (0, vtxs.size (), &vtxs [0]);
00634     vtx->vertex.deleteValues (vtxs.size ());
00635     grid->coordIndex.setValues (0, coords.size (), &coords [0]);
00636     grid->coordIndex.deleteValues (coords.size ());
00637 }
00638 
00639 void
00640 IgSoFieldPlane::convertMagFieldColors (double &minMag, double &maxMag)
00641 {
00642         float    rgb [3];
00643         double   mag;
00644         unsigned r,g,b,a;
00645         unsigned invisibleAlpha = invisible.getValue ();
00646         unsigned defaultAlpha   = alpha.getValue ();
00647         
00648         unsigned startColors = 0;
00649         
00650         for (unsigned regionIndex = 0; regionIndex < 5; regionIndex++)
00651         {
00652                 unsigned size = m_colorsMags[regionIndex].size ();
00653                 
00654                 if (size > 0)
00655                 {
00656                         std::vector<unsigned> colors (size, 0u);
00657                         // determine the color values for all magnitude values and put these into a 
00658                         // color array. Also determine the smallest and the greatest magnitude value
00659                         for (unsigned i = 0; i < size; i++)
00660                         {
00661                                 mag = m_colorsMags[regionIndex] [i];
00662                                 
00663                                 // looking for the smallest value greater zero
00664                                 if ((mag > 0.f) && (mag < minMag))
00665                                 {
00666                                         minMag = mag;
00667                                 }
00668                                 
00669                                 // looking for the greatest value
00670                                 if (mag > maxMag)
00671                                 {
00672                                         maxMag = mag;
00673                                 }
00674                                 
00675                                 // get a rgb color accoring to the value of mag (static method call)
00676                                 m_cmap->color (mag, rgb);
00677                                 
00678                                 r = int (rgb [0] * 255 + .5);
00679                                 g = int (rgb [1] * 255 + .5);
00680                                 b = int (rgb [2] * 255 + .5);
00681                                 a = mag < 1./256 ? invisibleAlpha : defaultAlpha;
00682                                 
00683                                 // yet another conversion: color vector to an unsigned integer
00684                                 colors [i] = r << 24 | g << 16 | b << 8 | a;
00685                         }
00686                         
00687                         // set the 'size' values of the color array from index 0 on
00688                         m_fieldPlane->orderedRGBA.setValues (startColors, size, &colors [0]);
00689                         startColors += size;
00690                         // deletes values from index 'size' upwards
00691                         m_fieldPlane->orderedRGBA.deleteValues (startColors);
00692                 }
00693         }
00694 }
00695 
00696 void
00697 IgSoFieldPlane::convertGradientScaleColors (double &minMag, double &maxMag)
00698 {
00699         float           rgb [3];
00700         double          mag;
00701         unsigned        r,g,b,a;
00702         unsigned        size = 0;
00703         
00704         for (unsigned i = 0; i < 5; i++)
00705         {
00706                 size += m_colorsMags[i].size ();
00707         }
00708         std::vector<unsigned>   colors (size, 0u);
00709         
00710         assert (dynamic_cast<IgSoFieldPlaneMap*> (m_gradientScale->getChild (0)));
00711         IgSoFieldPlaneMap *gs =
00712                 static_cast<IgSoFieldPlaneMap*> (m_gradientScale->getChild (0));
00713                 
00714         // the gradient scale's fix division
00715         size = 10;
00716         colors.resize ((size + 1) * 2);
00717         
00718         // check if there are any wrong values
00719         if (minMag < 0.f) { minMag = 0.f; }
00720         if (maxMag > 1.f) { maxMag = 1.f; }
00721 
00722         double delta = (maxMag - minMag)/(size);
00723         mag = minMag;
00724                 
00725         // determine the color values for the gradient scale
00726         // note that the loop has size + 1 iterations
00727         for (unsigned i = 0; i <= size; i++)
00728         {                       
00729                 m_cmap->color (mag, rgb);
00730                 
00731                 r = int (rgb [0] * 255 + .5);
00732                 g = int (rgb [1] * 255 + .5);
00733                 b = int (rgb [2] * 255 + .5);
00734                 a = 255;
00735                 
00736                 // first row of the stripe
00737                 colors [i] = r << 24 | g << 16 | b << 8 | a;
00738                 // second row of the stripe
00739                 colors [i+size+1] = colors [i];
00740                 mag += delta;
00741         }
00742         
00743         size = colors.size ();
00744         // set the color values for the gradient scale
00745         gs->orderedRGBA.setValues (0, size, &colors [0]);
00746         gs->orderedRGBA.deleteValues (size);
00747         
00748         // divide the scale into 10 by 1 patches
00749         gs->xdivs.set1Value (0, 10);
00750         gs->zdivs.set1Value (0, 1);
00751         
00752         // set the rest of the regions zero
00753         for (unsigned i = 1; i < 5; i++)
00754         {
00755                 gs->xdivs.set1Value (i, 0);
00756                 gs->zdivs.set1Value (i, 0);
00757         }
00758         
00759         gs->lowerLeftCorners.set1Value (0, gs->corners[0]);
00760         gs->upperRightCorners.set1Value (0, gs->corners[3]);
00761         gs->lowerRightCorners.set1Value (0, gs->corners[1]);    
00762 }
00763 
00764 void
00765 IgSoFieldPlane::refreshColors (void)
00766 {
00767         double minMag = 1.f;
00768         double maxMag = 0.f;
00769 
00770         convertMagFieldColors (minMag, maxMag);
00771         
00772         convertGradientScaleColors (minMag, maxMag);
00773                 
00774         // Now set the gradient scale's display values
00775         char    textLabel [20];
00776         double  clamp = maxvalue.getValue ();
00777         SoText2 *text;
00778         double  step = (maxMag - minMag)/4;
00779         double  mag = minMag;
00780         
00781         for (int i = 0; i < 5; i++)
00782         {
00783                 assert (dynamic_cast<SoText2*> (m_gradientScale->getChild (3 + (i * 2))));
00784                 text = static_cast<SoText2*> (m_gradientScale->getChild (3 + (i * 2)));
00785                 sprintf (textLabel, "%.4f", mag * clamp);
00786                 text->string = textLabel;
00787                 mag += step;
00788         }
00789 }
00790 
00791 void
00792 IgSoFieldPlane::resampleSegments (void)
00793 {
00794         // Basically we have a plane that is cut into 5 regions (0 to 4), 
00795         // the region 2 always represents the detailed window.
00796         m_xBaseDir = (m_fieldPlane->corners[1] - m_fieldPlane->corners[0]) / mapDensityX.getValue ();
00797         m_zBaseDir = (m_fieldPlane->corners[2] - m_fieldPlane->corners[0]) / mapDensityZ.getValue ();
00798         
00799         // clear all regions
00800         m_colorsMags.clear ();
00801         
00802         unsigned borderBitmask;
00803         borderBitmask = initializeParameters ();
00804 
00805         determineCorners (borderBitmask);
00806 
00807         transferValuesToMap ();
00808 
00809         calcColorMags ();
00810         
00811         // calculate magnetic field lines
00812         std::vector<SbVec3f>  segments;
00813         std::vector<int>      segidx;
00814         std::vector<unsigned> colors;
00815         unsigned              invisibleAlpha = invisible.getValue ();
00816         unsigned              defaultAlpha   = alpha.getValue ();
00817         Component             comp = (Component) component.getValue ();
00818         unsigned              division [2] = { mapDensityX.getValue (), mapDensityZ.getValue () };
00819     unsigned              subdiv   [2] = { segRatioX.getValue (), segRatioZ.getValue () };
00820         float                 clamp = maxvalue.getValue ();
00821 
00822         SbVec3f xdir = m_xBaseDir;
00823         SbVec3f zdir = m_zBaseDir; 
00824 
00825         float segscale = MINIMUM (xdir.length()*subdiv[0],zdir.length()*subdiv[1])
00826                                                 / clamp;        
00827 
00828         for (unsigned i = 0; i <= division [1]; ++i)
00829         {
00830                 for (unsigned j = 0; j <= division [0]; ++j)
00831                 {                       
00832                         // Prepare field position and get value.
00833                         SbVec3f from (m_fieldPlane->corners[0] + zdir * i + xdir * j);
00834                         double  pt [3] = { from [0], from [1], from [2] };
00835                         double  val [3];
00836                 
00837                         m_field->evaluate (pt, val);
00838                 
00839                         // Compute vertex colour and transparency from field
00840                         // value.  This depends on what components the client
00841                         // asked to see.
00842                         SbVec3f dir (val [0], val [1], val [2]);                        
00843                         double  mag;
00844                 
00845                         switch (comp)
00846                         {
00847                                 case XYZ_ALL:
00848                                         mag = MINIMUM (dir.length (), clamp) / clamp;
00849                                         break;
00850                         
00851                                 case XYZ_X:
00852                                         mag = MINIMUM (fabs (dir [0]), clamp) / clamp;
00853                                         break;
00854                         
00855                                 case XYZ_Y:
00856                                         mag = MINIMUM (fabs (dir [1]), clamp) / clamp;
00857                                         break;
00858                         
00859                                 case XYZ_Z:
00860                                         mag = MINIMUM (fabs (dir [2]), clamp) / clamp;
00861                                         break;
00862                         
00863                                 case XYZ_PHI:
00864                                 {
00865                                         SbVec3f radius (from [0], from [1], 0);
00866                                         radius.normalize ();
00867                                         SbVec3f angular (SbVec3f (0, 0, 1).cross (radius));
00868                                         mag = MINIMUM (fabs (angular.dot (dir)), clamp) / clamp;
00869                                 }
00870                                         break;
00871                         
00872                                 case XYZ_R:
00873                                 {
00874                                         SbVec3f radius (from [0], from [1], 0);
00875                                         radius.normalize ();
00876                                         mag = MINIMUM (fabs (radius.dot (dir)), clamp) / clamp;
00877                                 }
00878                                         break;
00879                         
00880                                 default:
00881                                         assert (false);
00882                                         mag = 0.;
00883                                         break;
00884                         }
00885                                                         
00886                         unsigned a = mag < 1./256 ? invisibleAlpha : defaultAlpha;
00887                         
00888                         // why/what is being done here? next time, at least write a hint please
00889                         if (i % subdiv [1] == 0 && j % subdiv [0] == 0 && a)
00890                         {
00891                                 unsigned index = segments.size ();
00892                                 segments.push_back (from);
00893                                 segments.push_back (from + dir * segscale);
00894                                 segidx.push_back (index);
00895                                 segidx.push_back (index + 1);
00896                                 segidx.push_back (SO_END_LINE_INDEX);
00897                         }
00898                 }
00899         }
00900         
00901         refreshColors ();
00902         
00903         SoVertexProperty *vtx;
00904         vtx = (SoVertexProperty *) m_segments->vertexProperty.getValue ();
00905         vtx->vertex.setValues (0, segments.size (), &segments [0]);
00906         vtx->vertex.deleteValues (segments.size ());
00907         m_segments->coordIndex.setValues (0, segidx.size (), &segidx [0]);
00908         m_segments->coordIndex.deleteValues (segidx.size ());
00909 }
00910 
00911 void
00912 IgSoFieldPlane::determineCorners (unsigned bitmask)
00913 {
00914         // This method determines the three corners of each region. lower left,
00915         // lower right and upper right corner. After that, the densities are 
00916         // accordingly calculated. Note that if the window is touching any border,
00917         // at least one region will have no volume, with the division/density 
00918         // being zero.
00919         //
00920         // below you see a schematic view of the regions 0-4 and corners marked 
00921         // by "o". All regions always keep their region index, i.e. the detailed 
00922         // window has the index 2.
00923         //
00924         // z
00925         // ^
00926         // |
00927         // +-----------o
00928         // |     4     |
00929         // o---o---o---o
00930         // | 1 | 2 | 3 |
00931         // o---o---o---o
00932         // |     0     |
00933         // o-----------o ---> x
00934         
00935         // if we dont have a detailed window, we just have one non-zero region
00936         // and the rest has zero density
00937         if ( m_sizeIsZero || (m_densityXTooLow && m_densityZTooLow) )
00938         {
00939                 m_regions[0].density[X_AXIS] = mapDensityX.getValue ();
00940                 m_regions[0].density[Z_AXIS] = mapDensityZ.getValue ();
00941                 m_regions[0].lowerLeft = m_fieldPlane->corners[0];
00942                 m_regions[0].upperRight = m_fieldPlane->corners[2] - m_fieldPlane->corners[0] + m_fieldPlane->corners[1];
00943                 m_regions[0].lowerRight = m_fieldPlane->corners[1];
00944                 
00945                 for (int i = 1; i < 5; i++)
00946                 {
00947                         // corners of regions with 0 density are ignored, so set them to 0
00948                         m_regions[i].density[X_AXIS] = 0;
00949                         m_regions[i].density[Z_AXIS] = 0;
00950                 }
00951         }
00952         else
00953         {
00954                 m_regions[0].lowerLeft = m_fieldPlane->corners[0];
00955                 m_regions[0].lowerRight = m_fieldPlane->corners[1];
00956                 
00957                 SbVec3f xdir = m_fieldPlane->corners[1] - m_fieldPlane->corners[0];
00958                 SbVec3f zdir = m_fieldPlane->corners[2] - m_fieldPlane->corners[0];
00959                 
00960                 m_regions[4].upperRight = m_fieldPlane->corners[2] - m_fieldPlane->corners[0] + m_fieldPlane->corners[1];
00961                 
00962                 SbLine leftEdge (m_fieldPlane->corners[0], m_fieldPlane->corners[2]);
00963                 SbLine rightEdge (m_fieldPlane->corners[1], m_regions[4].upperRight);
00964                 
00965                 // calculating the lower left, upper left, lower right and upper 
00966                 // right corner(s) of the window
00967                 m_regions[2].lowerLeft  = m_fieldPlane->corners[0] + (xdir * (m_window.origin[X_AXIS] + 1.0f - m_window.size[X_AXIS])  
00968                                                                         + zdir * (m_window.origin[Z_AXIS] + 1.0f - m_window.size[Z_AXIS])) / 2.0f;
00969                 m_regions[1].lowerRight = m_regions[2].lowerLeft;
00970                 m_regions[1].upperRight = m_regions[2].lowerLeft + m_zBaseDir * m_window.baseDiv[Z_AXIS];
00971                 m_regions[3].lowerLeft  = m_regions[2].lowerLeft + m_xBaseDir * m_window.baseDiv[X_AXIS];
00972                 m_regions[2].lowerRight = m_regions[3].lowerLeft;
00973                 m_regions[2].upperRight = m_regions[3].lowerLeft + m_zBaseDir * m_window.baseDiv[Z_AXIS];
00974                 
00975                 // projecting two corners of the window to the edges: lower left,
00976                 // lower right, upper left and upper right
00977                 m_regions[1].lowerLeft  = leftEdge.getClosestPoint (m_regions[2].lowerLeft);
00978                 m_regions[0].upperRight = rightEdge.getClosestPoint (m_regions[2].lowerLeft);
00979                 m_regions[3].lowerRight = m_regions[0].upperRight;
00980                 m_regions[4].lowerLeft  = leftEdge.getClosestPoint (m_regions[1].upperRight);
00981                 m_regions[3].upperRight = rightEdge.getClosestPoint (m_regions[1].upperRight);
00982                 m_regions[4].lowerRight = m_regions[3].upperRight;
00983 
00984                 unsigned mapDensX = mapDensityX.getValue ();
00985                 unsigned mapDensZ = mapDensityZ.getValue ();
00986                 
00987                 // now check the bitmask and calculate the according densities for each region
00988                 if ((bitmask & 2u) == 2u)
00989                 {
00990                         m_regions[0].density[X_AXIS] = 0;
00991                         m_regions[0].density[Z_AXIS] = 0;
00992                 }
00993                 else
00994                 {
00995                         m_regions[0].density[X_AXIS] = mapDensX;
00996                         m_regions[0].density[Z_AXIS] = (unsigned) round ((m_regions[1].lowerLeft - m_regions[0].lowerLeft).length () / m_zBaseDir.length ());
00997                 }
00998                 
00999                 if ((bitmask & 8u) == 8u)
01000                 {
01001                         m_regions[4].density[X_AXIS] = 0;
01002                         m_regions[4].density[Z_AXIS] = 0;
01003                 }
01004                 else
01005                 {
01006                         m_regions[4].density[X_AXIS] = mapDensX;
01007                         m_regions[4].density[Z_AXIS] = mapDensZ - m_regions[0].density[Z_AXIS] - m_window.baseDiv[Z_AXIS];
01008                 }
01009                 
01010                 if ((bitmask & 1u) == 1u)
01011                 {
01012                         m_regions[1].density[X_AXIS] = 0;
01013                         m_regions[1].density[Z_AXIS] = 0;
01014                 }
01015                 else
01016                 {
01017                         m_regions[1].density[X_AXIS] = (unsigned) round ((m_regions[2].lowerLeft - m_regions[1].lowerLeft).length () / m_xBaseDir.length ());
01018                         m_regions[1].density[Z_AXIS] = m_window.baseDiv[Z_AXIS];
01019                 }
01020                 
01021                 if ((bitmask & 4u) == 4u)
01022                 {
01023                         m_regions[3].density[X_AXIS] = 0;
01024                         m_regions[3].density[Z_AXIS] = 0;
01025                 }
01026                 else
01027                 {
01028                         m_regions[3].density[X_AXIS] = mapDensX - m_regions[1].density[X_AXIS] - m_window.baseDiv[X_AXIS];
01029                         m_regions[3].density[Z_AXIS] = m_window.baseDiv[Z_AXIS];
01030                 }
01031                 
01032                 // if all borders are touched by the window
01033                 if ((bitmask & 15u) == 15u)
01034                 {
01035                         m_regions[2].density[X_AXIS] = m_window.density[X_AXIS] * mapDensX;
01036                         m_regions[2].density[Z_AXIS] = m_window.density[Z_AXIS] * mapDensZ;
01037                 }
01038                 else
01039                 {
01040                         m_regions[2].density[X_AXIS] = (unsigned) round ((float) mapDensX * (float) m_window.density[X_AXIS] * m_window.size[X_AXIS]);
01041                         m_regions[2].density[Z_AXIS] = (unsigned) round ((float) mapDensZ * (float) m_window.density[Z_AXIS] * m_window.size[Z_AXIS]);
01042                 }
01043         }
01044 }
01045 
01046 void
01047 IgSoFieldPlane::correctDetailedSize ()
01048 {
01049         // in order to align the outer grids we need to calculate the apropriate
01050         // size of the inner window. the window density is always a integer 
01051         // multiple of the base density.
01052         unsigned mapDens[2];
01053         mapDens[X_AXIS] = mapDensityX.getValue ();
01054         mapDens[Z_AXIS] = mapDensityZ.getValue ();
01055         
01056         float smallest[2];
01057                 
01058         for (unsigned axis = X_AXIS; axis <= Z_AXIS; axis++)
01059         {
01060                 // smallest possible unit in the 'axis' dimension
01061                 smallest[axis] = 1.0f / (float) mapDens[axis];
01062                 
01063                 // find out how many _whole_ units are covered by the detailed window
01064                 m_window.baseDiv[axis] = (unsigned) round (m_window.size[axis] * mapDens[axis]);
01065 
01066                 // calculate that back to the size
01067                 m_window.size[axis] = ((float) m_window.baseDiv[axis] / (float) mapDens[axis]);
01068                 
01069                 // respect the case, in which the size becomes zero after the rounding, but we dont want that because we got a non-zero size from the user
01070                 if (m_window.size[axis] <= 0.0f)
01071                 {
01072                         m_window.size[axis] = smallest[axis];
01073                         m_window.baseDiv[axis] = 1;
01074                 }
01075         }
01076 }
01077 
01078 void
01079 IgSoFieldPlane::transferValuesToMap ()
01080 {
01081         // set the values on the map    
01082         m_fieldPlane->xdivs.set1Value (0, m_regions[0].density[X_AXIS]);
01083         m_fieldPlane->zdivs.set1Value (0, m_regions[0].density[Z_AXIS]);
01084         
01085         m_fieldPlane->lowerLeftCorners.set1Value (0, m_regions[0].lowerLeft);
01086         m_fieldPlane->upperRightCorners.set1Value (0, m_regions[0].upperRight);
01087         m_fieldPlane->lowerRightCorners.set1Value (0, m_regions[0].lowerRight);
01088         
01089         // in case we actually have a window to display
01090         if (! (m_sizeIsZero || (m_densityXTooLow && m_densityZTooLow) ))
01091         {
01092                 for (unsigned i = 1; i < 5; i++)
01093                 {
01094                         m_fieldPlane->xdivs.set1Value (i, m_regions[i].density[X_AXIS]);
01095                         m_fieldPlane->zdivs.set1Value (i, m_regions[i].density[Z_AXIS]);
01096                         
01097                         m_fieldPlane->lowerLeftCorners.set1Value (i, m_regions[i].lowerLeft);
01098                         m_fieldPlane->upperRightCorners.set1Value (i, m_regions[i].upperRight);
01099                         m_fieldPlane->lowerRightCorners.set1Value (i, m_regions[i].lowerRight);
01100                 }
01101         }
01102         else
01103         {
01104                 // set the fields zero
01105                 for (unsigned i = 1; i < 5; i++)
01106                 {
01107                         m_fieldPlane->xdivs.set1Value (i, 0);
01108                         m_fieldPlane->zdivs.set1Value (i, 0);
01109                 }
01110         }       
01111 }
01112 
01113 unsigned
01114 IgSoFieldPlane::initializeParameters ()
01115 {
01116         // Get the parameters for the detailed window, note that the window's
01117         // size is given in percent in the application, but for convienence 
01118         // of calculations later on we now divide it by 100. Throughout the 
01119         // code the words "density" and "division" are (used and mixed) and 
01120         // they are supposed to be the sampling density for a given region.
01121         
01122         const unsigned nbrOfRegions = 5u;
01123         unsigned borderBitmap = 0u;
01124         
01125         m_window.size[X_AXIS]    = winSizeX.getValue () / 100.0f;
01126         m_window.size[Z_AXIS]    = winSizeZ.getValue () / 100.0f;
01127         m_window.density[X_AXIS] = winDensityX.getValue ();
01128         m_window.density[Z_AXIS] = winDensityZ.getValue ();
01129         m_window.origin[X_AXIS]  = winOriginX.getValue ();
01130         m_window.origin[Z_AXIS]  = winOriginZ.getValue ();
01131 
01132         m_sizeIsZero = (m_window.size[X_AXIS] <= 0.0f || m_window.size[Z_AXIS] <= 0.0f);
01133         
01134         // it doesnt make sense to have a window with less than 2 times as 
01135         // dense grid
01136         m_densityXTooLow = m_window.density[X_AXIS] < 2;
01137         m_densityZTooLow = m_window.density[Z_AXIS] < 2;
01138         
01139         // skip the calculations if the area of the window is zero or the 
01140         // density of it is too low, i.e. we dont have a detailed window
01141         if ( !(m_sizeIsZero || (m_densityXTooLow && m_densityZTooLow)) )
01142         {
01143                 correctDetailedSize ();
01144                 
01145                 // The bitmap tells us which borders are touched by the window
01146                 borderBitmap = correctOriginAndGetMask ();
01147         }
01148         
01149         // create the empty color magnitude vectors for each region
01150         for (unsigned i = 0; i < nbrOfRegions; i++)
01151         {
01152                 m_colorsMags.push_back (std::vector<double> ());
01153         }
01154         return borderBitmap;
01155 }
01156 
01157 unsigned
01158 IgSoFieldPlane::correctOriginAndGetMask ()
01159 {
01160         // note: the window's coordinates are local coordinates in the plane
01161         // reaching from -1 to 1 in x and z direction. 
01162         
01163         // bitmask: lsb 1st bit = left border, 2nd bit = lower, 3rd bit = right, 4th bit = upper
01164         unsigned crossingBorder = 0u;
01165         
01166         unsigned mapDens[2];
01167         mapDens[X_AXIS] = mapDensityX.getValue ();
01168         mapDens[Z_AXIS] = mapDensityX.getValue ();
01169         
01170         // map the origin into the right place in order to fit the window into
01171         // the cells, i.e. there are no positions between the cells
01172         for (unsigned axis = X_AXIS; axis <= Z_AXIS; axis++)
01173         {
01174                 float position = mapDens[axis] * (m_window.origin[axis] + 1.0f) / 2.0f;
01175                 float roundedPos = round (position);
01176                 
01177                 if ((m_window.baseDiv[axis] % 2) == 1)
01178                 {
01179                         position = ((position > roundedPos) ? (roundedPos + 0.5) : (roundedPos - 0.5));
01180                 }
01181                 else
01182                 {
01183                         position = roundedPos;
01184                 }
01185                 
01186                 m_window.origin[axis] = (position * 2.0f / (float) mapDens[axis]) - 1.0f;
01187         }
01188 
01189         // The detailed window is not allowed to get out of the base plane's 
01190         // borders, therefore we have to correct the position of the origin 
01191         // in order to fit it into the base, since the window must have a 
01192         // non-zero size
01193         for (unsigned axis = X_AXIS; axis <= Z_AXIS; axis++)
01194         {
01195                 // left resp. lower border check
01196                 if ( m_window.origin[axis] <= (-1.0f + m_window.size[axis]) )
01197                 {
01198                         m_window.origin[axis] = -1.0f + m_window.size[axis];
01199                         crossingBorder = crossingBorder | (1u << axis);
01200                 }
01201         
01202                 // right resp. upper border check
01203                 if ( (1.0f - m_window.size[axis]) <= m_window.origin[axis] )
01204                 {
01205                         m_window.origin[axis] = 1.0f - m_window.size[axis];
01206                         crossingBorder = crossingBorder | (4u << axis);
01207                 }
01208         }
01209         return crossingBorder;
01210 }
01211 
01212 void 
01213 IgSoFieldPlane::calcColorMags ()
01214 {
01215 
01216         // Now loop over the regions. Precalculate the step vectors into
01217         // xdir and zdir: their lengths will match the sampling ratio in
01218         // that direction.
01219         //    
01220         // Note that we calculate a colour for every vertex, not just per
01221         // face.  In both directions there will be one more vertex than
01222         // there are faces.  The loop is traversed in i/z-major, j/x-minor
01223         // order as expected by IgSoFieldPlaneMap.
01224         
01225         Component comp = (Component) component.getValue ();
01226         float clamp = maxvalue.getValue ();
01227         SbVec3f xdir;
01228         SbVec3f zdir;
01229         
01230         // loop over 5 regions and calculate their color values and put them 
01231         // into the 5-dim vector, i.e. to eachregion belongs a dimension
01232         for (unsigned index = 0; index < 5; index++)
01233         {
01234                 // skip the calculation if the region has no volume
01235                 if (m_regions[index].density[X_AXIS] == 0 
01236                         || m_regions[index].density[Z_AXIS] == 0)
01237                 {
01238                         continue;
01239                 }
01240 
01241                 // take each regions length and density to calculate the unit step
01242                 // that has to be made to go across the area
01243                 xdir = (m_regions[index].lowerRight - m_regions[index].lowerLeft) / (float) m_regions[index].density[X_AXIS];
01244                 zdir = (m_regions[index].upperRight - m_regions[index].lowerRight) / (float) m_regions[index].density[Z_AXIS];
01245                 
01246                 for (unsigned i = 0; i <= m_regions[index].density [Z_AXIS]; ++i)
01247                 {
01248                         for (unsigned j = 0; j <= m_regions[index].density [X_AXIS]; ++j)
01249                         {
01250                                 // Prepare field position and get value.
01251                                 SbVec3f from (m_regions[index].lowerLeft + zdir * i + xdir * j);
01252                                 double  pt [3] = { from [0], from [1], from [2] };
01253                                 double  val [3];
01254                                 
01255                                 m_field->evaluate (pt, val);
01256                                 
01257                                 // Compute vertex colour and transparency from field
01258                                 // value. This depends on what components the client
01259                                 // asked to see.
01260                                 SbVec3f dir (val [0], val [1], val [2]);
01261                                 double  mag;
01262                         
01263                                 switch (comp)
01264                                 {
01265                                         case XYZ_ALL:
01266                                                 mag = MINIMUM (dir.length (), clamp) / clamp;
01267                                                 break;
01268                                 
01269                                         case XYZ_X:
01270                                                 mag = MINIMUM (fabs (dir [0]), clamp) / clamp;
01271                                                 break;
01272                                 
01273                                         case XYZ_Y:
01274                                                 mag = MINIMUM (fabs (dir [1]), clamp) / clamp;
01275                                                 break;
01276                                 
01277                                         case XYZ_Z:
01278                                                 mag = MINIMUM (fabs (dir [2]), clamp) / clamp;
01279                                                 break;
01280                                 
01281                                         case XYZ_PHI:
01282                                         {
01283                                                 SbVec3f radius (from [0], from [1], 0);
01284                                                 radius.normalize ();
01285                                                 SbVec3f angular (SbVec3f (0, 0, 1).cross (radius));
01286                                                 mag = MINIMUM (fabs (angular.dot (dir)), clamp) / clamp;
01287                                         }
01288                                                 break;
01289                                 
01290                                         case XYZ_R:
01291                                         {
01292                                                 SbVec3f radius (from [0], from [1], 0);
01293                                                 radius.normalize ();
01294                                                 mag = MINIMUM (fabs (radius.dot (dir)), clamp) / clamp;
01295                                         }
01296                                                 break;
01297                                 
01298                                         default:
01299                                                 assert (false);
01300                                                 mag = 0.;
01301                                                 break;
01302                                 }
01303                                         
01304                                 m_colorsMags[index].push_back (mag);
01305                         }
01306                 }
01307         }       
01308 }
01309 
01310 void
01311 IgSoFieldPlane::planeChanged (void *me, SoSensor *)
01312 {
01313     IgSoFieldPlane *self = static_cast<IgSoFieldPlane *> (me);
01314     self->m_mplaneSensor->detach ();
01315     self->m_manip->plane = self->plane;
01316     self->update ();
01317     self->m_mplaneSensor->attach (&self->m_manip->plane);
01318 }
01319 
01320 void
01321 IgSoFieldPlane::mplaneChanged (void *me, SoSensor *)
01322 {
01323     IgSoFieldPlane *self = static_cast<IgSoFieldPlane *> (me);
01324     self->m_planeSensor->detach ();
01325     self->plane = self->m_manip->plane;
01326     self->update ();
01327     self->m_planeSensor->attach (&self->plane);
01328 }
01329 
01330 void
01331 IgSoFieldPlane::showChanged (void *me, SoSensor *)
01332 {
01333     IgSoFieldPlane *self = static_cast<IgSoFieldPlane *> (me);
01334     self->buildStructure ();
01335     if (! self->show.getValue ())
01336         self->whichChild = SO_SWITCH_NONE;
01337     else
01338         self->whichChild = SO_SWITCH_ALL;
01339 }
01340 
01341 void
01342 IgSoFieldPlane::resampleSegmentsCB (void *me, SoSensor *)
01343 {
01344     IgSoFieldPlane *self = static_cast<IgSoFieldPlane *> (me);
01345     self->resampleSegments ();
01346 }
01347 
01348 void
01349 IgSoFieldPlane::showMapChanged (void *me, SoSensor *)
01350 {
01351     // field map should come before Gradient scale
01352     IgSoFieldPlane *self = static_cast<IgSoFieldPlane *> (me);
01353     self->buildStructure ();
01354     if (self->showMap.getValue ())
01355     {
01356         if (self->m_fieldPlane->getRefCount () == 1)
01357         {
01358             if (self->m_gradientScale->getRefCount () == 1)
01359                 self->addChild (self->m_fieldPlane);
01360             else
01361                 self->insertChild (self->m_fieldPlane,
01362                                    self->getNumChildren()-1);
01363         }
01364     }
01365     else if (self->m_fieldPlane->getRefCount () > 1)
01366         self->removeChild (self->m_fieldPlane);
01367 }
01368 
01369 void
01370 IgSoFieldPlane::gradientScaleChanged (void *me, SoSensor *)
01371 {
01372     // Gradient scale should always be the last child
01373     IgSoFieldPlane *self = static_cast<IgSoFieldPlane *> (me);
01374     self->buildStructure ();
01375     if (self->gradientScale.getValue ())
01376     {
01377         if (self->m_gradientScale->getRefCount () == 1)
01378             self->addChild (self->m_gradientScale);
01379     }
01380     else if (self->m_gradientScale->getRefCount () > 1)
01381         self->removeChild (self->m_gradientScale);
01382 }
01383 
01384 void
01385 IgSoFieldPlane::showSegmentsChanged (void *me, SoSensor *)
01386 {
01387     // Segments should be the 2nd child
01388     IgSoFieldPlane *self = static_cast<IgSoFieldPlane *> (me);
01389     self->buildStructure ();
01390     if (self->showSegments.getValue ())
01391     {
01392         if (self->m_segments->getRefCount () == 1)
01393             self->insertChild (self->m_segments, 2);
01394     }
01395     else if (self->m_segments->getRefCount () > 1)
01396         self->removeChild (self->m_segments);
01397 }

Generated on Tue Jun 9 17:38:45 2009 for CMSSW by  doxygen 1.5.4