VertexRotationHandle.cpp

Go to the documentation of this file.
00001 
00005 /* Copyright © 2009 James Legg.
00006     This program is free software: you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation, either version 3 of the License, or
00009     (at your option) any later version.
00010 */
00011 #include "VertexRotationHandle.h"
00012 
00013 #include <cmath>
00014 
00015 #include <GL/gl.h>
00016 
00017 #include <LinearMath/btQuaternion.h>
00018 
00019 #include "../path/Path.h"
00020 #include "../document/RotateVertexDelta.h"
00021 
00022 #include <Debug.h>
00023 
00024 namespace Track
00025 {
00026 
00027 namespace EditAssist
00028 {
00029 
00030 
00031 VertexRotationHandle::VertexRotationHandle(std::size_t vertex_id, Direction direction)
00032     :   vertex_id(vertex_id)
00033     ,   direction (direction)
00034 {
00035     length = 1.0;
00036 }
00037 
00038 boost::shared_ptr<Document::DocumentDelta> VertexRotationHandle::make_delta(btVector3 new_position) const
00039 {
00040     /* Find an angle with minimal difference to the last one that fits the new
00041      * position.
00042      */
00043     btVector3 new_vector = (new_position - centre) / length;
00044     btVector3 old_vector = (position - centre) / length;
00045     btVector3 cross = old_vector.cross(new_vector);
00046     bool obtuse = (new_vector + old_vector).length2() < 2;
00047     btScalar sin_angle = cross.length();
00048     
00049     // some floating point rounding fixes:
00050     if (std::fabs(sin_angle) < 0.002)
00051     {
00052         if (!obtuse)
00053         {
00054             DEBUG_MESSAGE("Rotation too small, ignoring.");
00055             // Didn't rotate very far.
00056             // Vector is very short: just act as if there was no rotation to
00057             // avoid problems normalising it.
00058             return boost::shared_ptr<Document::DocumentDelta>
00059             (
00060                 new Document::RotateVertexDelta
00061                 (
00062                     Document::VertexAngleFinder(vertex_id),
00063                     rotation
00064                 )
00065             );
00066         }
00067         else
00068         {
00069             // We can't rely on the direction we are rotating about, but
00070             // need to rotate about 180 degrees. Guess a direction.
00071             DEBUG_MESSAGE("Rotation too close to 180 degrees, guessing direction.");
00072             return boost::shared_ptr<Document::DocumentDelta>
00073             (
00074                 new Document::RotateVertexDelta
00075                 (
00076                     Document::VertexAngleFinder(vertex_id),
00078                     rotation * btQuaternion(btVector3(0, 0, 1), M_PI)
00079                 )
00080             );
00081         }
00082     }
00083     // sin_angle might be just outside the valid range.
00084     if (sin_angle > 1.0) sin_angle = 1.0;
00085     
00086     btScalar angle = std::asin(sin_angle);
00087     if (obtuse)
00088     {
00089         angle = M_PI - angle;
00090     }
00091     
00092     cross.normalize();
00093     btQuaternion rotation_difference(cross, angle);
00094     btQuaternion new_angle(rotation_difference * rotation);
00095     
00096     return boost::shared_ptr<Document::DocumentDelta>
00097     (
00098         new Document::RotateVertexDelta
00099         (
00100             Document::VertexAngleFinder(vertex_id),
00101             new_angle
00102         )
00103     );
00104 }
00105 
00106 void VertexRotationHandle::update_angle(btQuaternion angle_in)
00107 {
00108     /* The position is centre position + the a vector in the direction the
00109      * handle indicates with the requested length.
00110      */
00111     rotation = angle_in;
00112     position = centre + length * 
00113         btTransform(angle_in)(direction == DIR_FORWARD ? btVector3(0, 1, 0) : btVector3(0, 0, 1));
00114 }
00115 
00116 void VertexRotationHandle::draw() const
00117 {
00118     switch (direction)
00119     {
00120         case DIR_FORWARD:
00121             glColor3ub(0, 255, 0);
00122             break;
00123         case DIR_UP:
00124             glColor3ub(255, 0, 0);
00125             break;
00126     }
00127     RotationHandle::draw();
00128 }
00129 
00130 }
00131 
00132 }
00133 

Get Racer at SourceForge.net. Fast, secure and Free Open Source software downloads

Generated at Mon Sep 6 00:41:11 2010 by Doxygen version 1.4.7 for Racer version svn335.