Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

robot/sim/VisualIKORTest.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)2003 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (at your option) any later version.
00008   
00009   This program is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012   GNU General Public License for more details. (http://www.gnu.org)
00013   
00014   You should have received a copy of the GNU General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017   
00018   $Id: VisualIKORTest.cpp 1033 2004-02-11 20:47:52Z jungd $
00019   $Revision: 1.7 $
00020   $Date: 2004-02-11 15:47:52 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022  
00023 ****************************************************************************/
00024 
00025 #include <robot/sim/VisualIKORTest>
00026 
00027 #include <base/Externalizer>
00028 #include <base/externalization_error>
00029 #include <base/Expression>
00030 #include <base/Matrix>
00031 #include <base/VDirectory>
00032 #include <base/VFile>
00033 
00034 #include <osg/Group>
00035 #include <osg/Switch>
00036 #include <osg/Geode>
00037 #include <osg/Geometry>
00038 #include <osgText/Font>
00039 #include <osgText/Text>
00040 
00041 
00042 using robot::sim::VisualIKORTest;
00043 
00044 using base::Vector;
00045 using base::Orient;
00046 using base::Time;
00047 using base::PathName;
00048 using base::VFile;
00049 using base::VDirectory;
00050 using base::externalization_error;
00051 using base::Path;
00052 using base::Trajectory;
00053 using base::dom::DOMNode;
00054 using base::dom::DOMElement;
00055 using gfx::Segment3;
00056 using gfx::Color4;
00057 using robot::sim::IKORTest;
00058 using robot::sim::BasicEnvironment;
00059 using robot::control::kinematics::FullSpaceSolver;
00060 using robot::control::kinematics::InverseKinematicsSolver;
00061 using robot::control::kinematics::FullSpaceSolver;
00062 using robot::control::kinematics::IKOR;
00063 
00064 
00065 
00066 
00067 
00068 VisualIKORTest::VisualIKORTest(ref<base::VFile> testSpecification,
00069                                ref<base::VFileSystem> fs, ref<base::Cache> cache)
00070   : IKORTest(testSpecification, fs, cache)
00071 {
00072 }
00073 
00074 
00075 
00076 osg::Vec3Array* VisualIKORTest::newVertexArrayFromLines(const VisualIKORTest::LineSegArray& lines)
00077 {
00078   osg::Vec3Array& v(*NewObj osg::Vec3Array(lines.size()*2));
00079   for(Int i=0; i<lines.size(); i++) {
00080     const Point3& s(lines[i].s);
00081     const Point3& e(lines[i].e);
00082     v[2*i].set(s.x,s.y,s.z);
00083     v[2*i+1].set(e.x,e.y,e.z);
00084   }
00085   return &v;
00086 }
00087 
00088 
00089 osg::Geometry* VisualIKORTest::newGeometryFromLines(const VisualIKORTest::LineSegArray& lines, const gfx::Color4& color)
00090 {
00091   osg::Geometry* linesGeom = new osg::Geometry();
00092   osg::Vec3Array* verts(newVertexArrayFromLines(lines));
00093   linesGeom->setVertexArray(verts);
00094   osg::Vec4Array& colora(*new osg::Vec4Array(1));
00095   colora[0].set(color.r, color.g, color.b, color.a);
00096   linesGeom->setColorArray(&colora);
00097   linesGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
00098   linesGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINES,0,lines.size()*2));
00099   return linesGeom;
00100 }
00101 
00102 
00103 
00104 VisualIKORTest::LineSegArray VisualIKORTest::manipToolAsLines(const KinematicChain& chain, const Vector& q, Int numPlatformLinks)
00105 {
00106   // create lines between each pair of link origins, except those for the platform
00107   LineSegArray lines;
00108 //Debugcln(DJ,"q=" << q << "(chain size=" << chain.size() << ")" << std::flush);
00109 
00110   array<Vector> links( chain.getLinkOrigins(q) );
00111   for(Int l=numPlatformLinks+1; l<links.size(); l++) {
00112     const Vector& plink(links[l-1]);
00113     const Vector& link( links[l]);
00114     lines.push_back(Segment3(Point3(plink[0],plink[1],plink[2]), Point3(link[0],link[1],link[2])));
00115     // debug!!!!
00116     lines.push_back(Segment3(Point3(link[0],link[1],link[2]), Point3(link[0],link[1],link[2]+0.05)));
00117   }
00118   
00119   return lines;
00120 }
00121 
00122 
00123 VisualIKORTest::LineSegArray VisualIKORTest::platformAsLines(ref<const PlatformDescription> platfDescr, 
00124                                                              const KinematicChain& platfChain, 
00125                                                              const Vector& q, Real steerAngle)
00126 {
00127   // draw the platform as a square with line-seg wheels 
00128   LineSegArray lines;
00129 
00130   const base::Dimension3 dim(platfDescr->dimensions());
00131   Vector3 offset(platfDescr->originOffset());
00132   
00133   Vector3 c1(-dim.x/2.0, -dim.y/2.0, 0), c2(-dim.x/2.0, dim.y/2.0, 0),  // corners
00134           c3(dim.x/2.0, dim.y/2.0, 0), c4(dim.x/2.0, -dim.y/2.0, 0);
00135   c1-=offset; c2-=offset; c3-=offset; c4-=offset;
00136 
00137   Vector pf_q;
00138   if (platfChain.dof() > 0) pf_q = vectorRange(q,Range(0,platfChain.dof()));
00139   Matrix4 pT(base::toMatrix4(platfChain.getForwardKinematics(pf_q)));
00140   c1 = pT*c1; c2 = pT*c2; c3 = pT*c3; c4 = pT*c4; // transform to world frame
00141   
00142   lines.push_back(Segment3(c1,c2));
00143   lines.push_back(Segment3(c2,c3));
00144   lines.push_back(Segment3(c3,c4));
00145   lines.push_back(Segment3(c4,c1));
00146 /*
00147   // the wheels
00148   const Real d = 0.4; // wheel diameter (length of 2D proj)
00149   const Real L = platfDescr.L();
00150   const Real W = platfDescr.W();
00151   
00152   // back
00153   Vector3 bwlb(-L-d/2.0, 0.8*(dim.y/2.0), -offset.z);  // back wheel left back point
00154   Vector3 bwlf(-L+d/2.0, 0.8*(dim.y/2.0), -offset.z);
00155   Vector3 bwrb(-L-d/2.0, 0.8*(-dim.y/2.0), -offset.z);
00156   Vector3 bwrf(-L+d/2.0, 0.8*(-dim.y/2.0), -offset.z);
00157   
00158   bwlb = pT*bwlb; bwlf = pT*bwlf; bwrb = pT*bwrb; bwrf = pT*bwrf; // to world
00159   lines.push_back(Segment3(bwlb,bwlf));
00160   lines.push_back(Segment3(bwrb,bwrf));
00161 
00162 
00163   // front
00164   Real dx = (d/2.0)*cos(steerAngle);
00165   Real dy = (d/2.0)*sin(steerAngle);
00166   Vector3 fwlb(-L+W-dx, 0.8*(dim.y/2.0)+dy, -offset.z); // front wheel left back point
00167   Vector3 fwlf(-L+W+dx, 0.8*(dim.y/2.0)-dy, -offset.z);
00168   Vector3 fwrb(-L+W-dx, 0.8*(-dim.y/2.0)+dy, -offset.z);
00169   Vector3 fwrf(-L+W+dx, 0.8*(-dim.y/2.0)-dy, -offset.z);
00170 
00171   fwlb = pT*fwlb; fwlf = pT*fwlf; fwrb = pT*fwrb; fwrf = pT*fwrf; // to world
00172   lines.push_back(Segment3(fwlb,fwlf));
00173   lines.push_back(Segment3(fwrb,fwrf));
00174 */
00175   
00176   return lines;
00177 }
00178 
00179 
00180 /// helper to translate a segment
00181 static inline gfx::Segment3 translate(const gfx::Segment3& s, const base::Vector3& t) 
00182 {
00183   gfx::Segment3 ts(s); ts.s += t; ts.e += t;
00184   return ts;
00185 }
00186 
00187 
00188 VisualIKORTest::LineSegArray VisualIKORTest::obstaclesAsLines(ref<const BasicEnvironment> env)
00189 {
00190   LineSegArray lines;
00191 
00192   for(Int i=0; i<env->numObstacles(); i++) {
00193     ref<const BasicEnvironment::Obstacle> obst(env->getObstacle(i));
00194     
00195     switch (obst->type) {
00196 
00197     case BasicEnvironment::Obstacle::BoxObstacle: {
00198       const base::Dimension3& dim(obst->dims);
00199       Vector3 c1(-dim.x/2.0, -dim.y/2.0, -dim.z/2.0), c2(-dim.x/2.0, dim.y/2.0, -dim.z/2.0),  // corners
00200               c3(dim.x/2.0, dim.y/2.0, -dim.z/2.0), c4(dim.x/2.0, -dim.y/2.0, -dim.z/2.0);
00201       Vector3 c5(-dim.x/2.0, -dim.y/2.0, dim.z/2.0), c6(-dim.x/2.0, dim.y/2.0, dim.z/2.0),  
00202               c7(dim.x/2.0, dim.y/2.0, dim.z/2.0), c8(dim.x/2.0, -dim.y/2.0, dim.z/2.0);
00203               
00204       // transform
00205       Matrix4 T( obst->orientation.getRotationMatrix3() );
00206       T.setTranslationComponent( obst->position );
00207       c1 = T*c1; c2 = T*c2; c3 = T*c3; c4 = T*c4;
00208       c5 = T*c5; c6 = T*c6; c7 = T*c7; c8 = T*c8;
00209               
00210       // bottom
00211       lines.push_back(Segment3(c1,c2));
00212       lines.push_back(Segment3(c2,c3));
00213       lines.push_back(Segment3(c3,c4));
00214       lines.push_back(Segment3(c4,c1));
00215       
00216       // top
00217       lines.push_back(Segment3(c5,c6));
00218       lines.push_back(Segment3(c6,c7));
00219       lines.push_back(Segment3(c7,c8));
00220       lines.push_back(Segment3(c8,c5));
00221       
00222       // sides
00223       lines.push_back(Segment3(c1,c5));
00224       lines.push_back(Segment3(c2,c6));
00225       lines.push_back(Segment3(c3,c7));
00226       lines.push_back(Segment3(c4,c8));
00227     } break;
00228     
00229     case BasicEnvironment::Obstacle::SphereObstacle: {
00230       // compute segments for 6 circles; 3 in each of the xy, yz and xz planes & 3 rotated
00231       Transform rot(Orient(consts::Pi/4.0, consts::Pi/4.0, 0)); // roll 45, pitch 45
00232       
00233       Real r = obst->radius;
00234       Point3 c = obst->position;
00235       Real inc = consts::Pi/32.0;
00236       for(Real a=inc; a<=2*consts::Pi; a+=inc) {
00237         Real c1 = r*cos(a-inc);
00238         Real s1 = r*sin(a-inc);
00239         Real c2 = r*cos(a);
00240         Real s2 = r*sin(a);
00241         
00242         Point3 xy1( c1, s1, 0); 
00243         Point3 xy2( c2, s2, 0); 
00244         Segment3 xy(xy1, xy2);
00245         lines.push_back(translate(xy,c));
00246         xy.transform(rot);
00247         lines.push_back(translate(xy,c));
00248         Point3 yz1( 0, c1, s1); 
00249         Point3 yz2( 0, c2, s2); 
00250         Segment3 yz(yz1, yz2);
00251         lines.push_back(translate(yz,c));
00252         yz.transform(rot);
00253         lines.push_back(translate(yz,c));
00254         Point3 xz1( c1, 0, s1); 
00255         Point3 xz2( c2, 0, s2); 
00256         Segment3 xz(xz1,xz2);
00257         lines.push_back(translate(xz,c));
00258         xz.transform(rot);
00259         lines.push_back(translate(xz,c));
00260          
00261       }
00262             
00263     } break;
00264     
00265     default:
00266       Logfln("warning: unknown obstacle type (" << obst->type << ") not displayed");
00267     }
00268     
00269   }
00270   
00271   return lines;
00272 }
00273 
00274   
00275   
00276 VisualIKORTest::LineSegArray VisualIKORTest::trajectoryAsLines(const array<base::Vector>& xs)
00277 {
00278   LineSegArray lines;
00279 
00280   for(Int i=0; i<xs.size()-1; i++) {
00281     const Vector& xi(xs[i]);
00282     const Vector& xip1(xs[i+1]);
00283     lines.push_back(Segment3(Point3(xi[0],xi[1],xi[2]), Point3(xip1[0],xip1[1],xip1[2])));
00284   }
00285   
00286   return lines;
00287 }
00288 
00289   
00290   
00291   
00292 osg::Node* VisualIKORTest::createOSGVisual(Attributes visualAttributes) const
00293 {
00294   if ((node!=0) && (attributes==visualAttributes))
00295     return &(*node);
00296   
00297   osg::Switch* worldNode = new osg::Switch();
00298   worldNode->addChild( osgCreateObstacles() );
00299   worldNode->addChild( osgCreateAxes() );
00300   worldNode->addChild( osgCreateTrajectory() );
00301 
00302   worldNode->addChild( osgCreateManipulator() );
00303   
00304   worldNode->setAllChildrenOn();
00305   worldNode->setValue(0,displayObstacles);
00306   worldNode->setValue(1,displayAxes);
00307   worldNode->setValue(2,displayEEPath);
00308   
00309   worldNode->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
00310 
00311   node = worldNode;
00312   return &(*node);
00313 }
00314 
00315 
00316 
00317 osg::Node*  VisualIKORTest::osgCreateAxes() const
00318 {
00319   const Real l = 1.0; // axis length
00320   const Real charSize = 0.2;
00321   osg::Vec4 labelCol(0,0,0,1);
00322   
00323   osg::Geode* geode = new osg::Geode();
00324 
00325   LineSegArray axes;
00326   axes.push_back(Vector3(l,0,0));
00327   axes.push_back(Vector3(0,l,0));
00328   axes.push_back(Vector3(0,0,l));
00329   osg::Geometry* linesGeom = newGeometryFromLines(axes, Color4(0.5,0.5,0.5));
00330   geode->addDrawable(linesGeom);
00331 
00332   // labels
00333   String font("fonts/times.ttf");
00334 
00335   osgText::Text* xtext = new osgText::Text;
00336   xtext->setFont(font);
00337   xtext->setCharacterSize(charSize);
00338   xtext->setFontSize(20,20);
00339   xtext->setColor(labelCol);
00340   xtext->setPosition(osg::Vec3(1.05,0,0));
00341   xtext->setAxisAlignment(osgText::Text::SCREEN);
00342   xtext->setText("X");
00343   geode->addDrawable(xtext);
00344 
00345   osgText::Text* ytext = new osgText::Text;
00346   ytext->setFont(font);
00347   ytext->setCharacterSize(charSize);
00348   ytext->setFontSize(20,20);
00349   ytext->setColor(labelCol);
00350   ytext->setPosition(osg::Vec3(0,1.05,0));
00351   ytext->setAxisAlignment(osgText::Text::SCREEN);
00352   ytext->setText("Y");
00353   geode->addDrawable(ytext);
00354 
00355   osgText::Text* ztext = new osgText::Text;
00356   ztext->setFont(font);
00357   ztext->setCharacterSize(charSize);
00358   ztext->setFontSize(20,20);
00359   ztext->setColor(labelCol);
00360   ztext->setPosition(osg::Vec3(0,0,1.05));
00361   ztext->setAxisAlignment(osgText::Text::SCREEN);
00362   ztext->setText("Z");
00363   geode->addDrawable(ztext);
00364   
00365   return geode;
00366 }
00367 
00368 
00369 osg::Node* VisualIKORTest::osgCreateObstacles() const
00370 {
00371   osg::Geode* geode = new osg::Geode();
00372   geode->addDrawable( newGeometryFromLines(obstaclesAsLines(env),Color4(0.3,0.3,0.9)) );
00373   return geode;
00374 }     
00375       
00376 
00377 osg::Node* VisualIKORTest::osgCreateManipulator() const
00378 {
00379   ref<const BasicEnvironment> env(getEnvironment());
00380   ref<const SimulatedRobot> robot( narrow_ref<const SimulatedRobot>(getRobot()) );
00381   Int testManipulatorIndex = getManipulatorIndex();
00382   
00383   ref<const RobotDescription> robotDescr(robot->getRobotDescription());
00384   ref<const PlatformDescription> platfDescr(robotDescr->platform() );
00385 
00386   Matrix4 platformTransform( robot->getOrientation().getRotationMatrix3() );
00387   platformTransform.setTranslationComponent( robot->getPosition() );
00388 
00389   KinematicChain robotChain(robotDescr->getKinematicChain(3,platformTransform,testManipulatorIndex,0));
00390   KinematicChain platfChain(platfDescr->getKinematicChain(3,platformTransform));
00391   Int numPlatfLinks = platfChain.size();
00392 
00393   // make each test a seperate child in a Group
00394   osg::Group* testsGroup = new osg::Group();
00395 
00396   Int stepCount=0;  
00397   for(Int t=0; t<tests.size(); t++) { // for each test
00398     const Test& test(tests[t]);
00399     
00400     KinematicChain chain(robotChain); // kinematic chain from world frame to manip/tool end-effector
00401 
00402     // locate tool
00403     bool toolAttached = false;
00404     if (test.toolAttached) {
00405       for(Int i=0; (i<env->numTools()) && !toolAttached; i++) {
00406         ref<const ToolDescription> td( env->getTool(i)->getToolDescription() );
00407         
00408         if (td->getName() == test.toolName) {
00409           toolAttached = true;
00410           KinematicChain toolChain( td->getKinematicChain() );
00411           chain += toolChain;
00412         }
00413       }
00414     }
00415     
00416     // create a Switch with each test joint space state of the manipulator represented as a child
00417     //  and platform (independently)
00418     osg::Switch* testPlatfSwitch = new osg::Switch();
00419     osg::Switch* testManipSwitch = new osg::Switch();
00420     
00421     Vector pf_prevq(platfChain.dof());
00422     Vector pf_q(platfChain.dof());
00423     
00424     for(Int i=0; i<test.qs.size(); i++) {
00425       const Vector& q( test.qs[i] );
00426       
00427       osg::Geode* platfGeode = new osg::Geode();
00428       osg::Geode* manipGeode = new osg::Geode();
00429 
00430       pf_prevq = pf_q;
00431       pf_q = vectorRange(q, Range(0, platfChain.dof()) );
00432       if(i==0) pf_prevq = pf_q;
00433       
00434       Real steerAngle = platfDescr->requiredSteeringAngle(pf_prevq, pf_q);
00435       
00436       platfGeode->addDrawable( newGeometryFromLines(platformAsLines(platfDescr,platfChain,pf_q,steerAngle ),
00437                             Color4(0.4,0.4,0.4)) );
00438 
00439       manipGeode->addDrawable( newGeometryFromLines(manipToolAsLines(chain,q,numPlatfLinks),Color4(0.3,0.3,0.3)) );
00440 
00441       stepCount++;
00442       
00443       testPlatfSwitch->addChild(platfGeode);
00444       testManipSwitch->addChild(manipGeode);
00445       if (test.displayRangeSpecified) {
00446         testPlatfSwitch->setValue(i, ((i >= test.displayStartIndex) && (i < test.displayEndIndex) && ((stepCount%displayStepMod) == 0) && displayPlatform ) );
00447         testManipSwitch->setValue(i, ((i >= test.displayStartIndex) && (i < test.displayEndIndex) && ((stepCount%displayStepMod) == 0)  ) );
00448       }
00449       else {
00450         testPlatfSwitch->setValue(i, ((stepCount%displayStepMod) == 0) && displayPlatform );
00451         testManipSwitch->setValue(i, (stepCount%displayStepMod) == 0);
00452       }
00453     }
00454     
00455     testPlatfSwitches.push_back( testPlatfSwitch );
00456     testManipSwitches.push_back( testManipSwitch );
00457     testsGroup->addChild( testPlatfSwitch );
00458     testsGroup->addChild( testManipSwitch );
00459   }
00460 
00461   return testsGroup;
00462 }
00463 
00464 
00465 osg::Node* VisualIKORTest::osgCreateTrajectory() const
00466 {
00467   osg::Geode* geode = new osg::Geode();
00468   
00469   for(Int t=0; t<tests.size(); t++) { // for each test
00470     const Test& test(tests[t]);
00471     geode->addDrawable( newGeometryFromLines(trajectoryAsLines(test.xs),Color4(0.9,0.3,0.3)) );
00472   }
00473   return geode;
00474 }     
00475 
00476   
00477 void VisualIKORTest::updateVisuals() const
00478 {
00479   if ((node == 0)  || (testPlatfSwitches.size()==0)) return;
00480   
00481   node->setValue(0, displayObstacles);
00482   node->setValue(1, displayAxes);
00483   node->setValue(2, displayEEPath);
00484 
00485   Int stepCount=0;  
00486   for(Int t=0; t<tests.size(); t++) { // for each test
00487     const Test& test(tests[t]); 
00488   
00489     osg::Switch* testPlatfSwitch = &(*testPlatfSwitches[t]);
00490     osg::Switch* testManipSwitch = &(*testManipSwitches[t]);
00491     for(Int i=0; i<test.times.size(); i++) {
00492       testPlatfSwitch->setValue(i, ((i >= test.displayStartIndex) && (i < test.displayEndIndex) && ((stepCount%displayStepMod)==0) && displayPlatform ));
00493       testManipSwitch->setValue(i, ((i >= test.displayStartIndex) && (i < test.displayEndIndex) && ((stepCount%displayStepMod)==0) ));
00494       stepCount++;
00495     }
00496 
00497   }
00498   
00499 }
00500 
00501   
00502   
00503 void VisualIKORTest::svgLine(base::Externalizer& e, base::dom::DOMElement* svgElem, const gfx::Segment3& line) const
00504 {
00505   Point3 start(line.s);
00506   Point3 end(line.e);
00507   start = svgTransform*start;
00508   end = svgTransform*end;
00509   
00510   DOMElement* lineElem = e.createElement("line");
00511   e.setElementAttribute(lineElem, "x1", base::realToString(start.x));
00512   e.setElementAttribute(lineElem, "y1", base::realToString(start.y));
00513   e.setElementAttribute(lineElem, "x2", base::realToString(end.x));
00514   e.setElementAttribute(lineElem, "y2", base::realToString(end.y));
00515   //e.setElementAttribute(lineElem, "stroke", "stroke-width:0.5");
00516   e.appendNode(svgElem, lineElem);
00517   
00518 }
00519 
00520 
00521 void VisualIKORTest::svgLines(base::Externalizer& e, base::dom::DOMElement* svgElem, const LineSegArray& lines) const
00522 {
00523   for(Int l=0; l<lines.size(); l++)
00524     svgLine(e, svgElem, lines[l]);
00525 }
00526 
00527 
00528 void VisualIKORTest::svgText(base::Externalizer& e, base::dom::DOMElement* svgElem, const Point3& pos, const String& text, Real size) const
00529 {
00530   DOMElement* textElem = e.createElement("text");
00531   e.setElementAttribute(textElem, "x", base::realToString(pos.x));
00532   e.setElementAttribute(textElem, "y", base::realToString(pos.y));
00533   e.setElementAttribute(textElem, "style", "font-size:"+base::realToString(size)
00534                                            +"; font-family:Arial, sans-serif");
00535   e.appendText(textElem, text);
00536   e.appendNode(svgElem, textElem);
00537 }
00538 
00539   
00540 
00541 void VisualIKORTest::svgOutputAxes(base::Externalizer& e, base::dom::DOMElement* svgElem) const
00542 {
00543   const Real l = 1.0; // axis length
00544   
00545   LineSegArray axes;
00546   axes.push_back(Vector3(l,0,0));
00547   axes.push_back(Vector3(0,l,0));
00548   axes.push_back(Vector3(0,0,l));
00549 
00550   svgLines(e, svgElem, axes);  
00551   
00552   svgText(e, svgElem, Point3(1,0,0), "X");
00553   svgText(e, svgElem, Point3(0,1,0), "Y");
00554   svgText(e, svgElem, Point3(0,0,1), "Z");
00555 }
00556 
00557   
00558   
00559 
00560 void VisualIKORTest::externalize(base::Externalizer& e, String format, Real version)
00561 {
00562   if (format == "") format = "xml";
00563   
00564   if (!formatSupported(format,version,e.ioType()))
00565     throw std::invalid_argument(Exception(String("format ")+format+" v"+base::realToString(version)+" unsupported"));
00566 
00567   if (format == "xml") 
00568     IKORTest::externalize(e,format,version);
00569   else if (format == "svg") {
00570 
00571     if (e.isInput()) {
00572       Unimplemented;
00573     }
00574     else { // output
00575         
00576         svgTransform.setIdentity();
00577         
00578         // must set type before first element is created (ignored if e is not a new output Externalizer)
00579         e.setDocumentType("svg","-//W3C//DTD SVG 20010904//EN",
00580                           "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd");
00581 
00582         // createElement must be called first, as it will create to document root element if e is a new output Externalizer
00583         DOMElement* svgElem = e.createElement("svg");
00584         
00585         e.setElementAttribute(svgElem, "xmlns", "http://www.w3.org/2000/svg");
00586         e.setElementAttribute(svgElem, "width", "100%");
00587         e.setElementAttribute(svgElem, "height", "100%");
00588         
00589         
00590         svgOutputAxes(e, svgElem);
00591         
00592         
00593         e.appendElement(svgElem);
00594         e.appendBreak(svgElem);      
00595     
00596         
00597     }
00598     
00599   }
00600 
00601 }

Generated on Thu Jul 29 15:56:44 2004 for OpenSim by doxygen 1.3.6