AnnotationObject.qt.C

00001 #ifndef ANNOTATIONOBJECT_QT_C
00002 #define ANNOTATIONOBJECT_QT_C
00003 
00004 #include <math.h>
00005 
00006 #include "NeovisionII/NeoAnnotate/AnnotationObject.qt.H"
00007 #include "Util/log.H"
00008 #include "NeovisionII/NeoAnnotate/ObjectAnimation.qt.H"
00009 #include "NeovisionII/NeoAnnotate/AnimationDelegate.qt.H"
00010 #include "rutz/trace.h"
00011 
00012 
00013 #undef GVX_TRACE_EXPR
00014 #define GVX_TRACE_EXPR false
00015 
00016 qreal distanceToLine(QLineF line, QPointF point);
00017 
00018 int AnnotationObject::theirIdCount = 1;
00019 
00020 //######################################################################
00021 AnnotationObjectVertex::AnnotationObjectVertex(AnnotationObject *parent, int frameNum, FrameRange frameRange, QPointF initialPos) :
00022   QGraphicsItem(parent), itsVertexSize(-4, -4, 8, 8), itsParent(parent),
00023   itsAnimation(new ObjectAnimation(frameNum, frameRange, initialPos))
00024 {
00025   //Tell Qt that this item is available for drag & drop, and to no
00026   //apply scaling transformations to it as we zoom
00027   setFlags(
00028       QGraphicsItem::ItemIsMovable    |
00029       QGraphicsItem::ItemIgnoresTransformations |
00030       QGraphicsItem::ItemSendsGeometryChanges
00031       );
00032 
00033   setPos(initialPos);
00034 
00035   //Tell Qt to accept hover events over this vertex
00036 #if INVT_QT4_MINOR >= 4
00037   setAcceptHoverEvents(true);
00038 #else
00039   setAcceptsHoverEvents(true);
00040 #endif
00041 
00042   itsColor = itsParent->getColor();
00043   itsColor.setAlpha(128);
00044 
00045   itsBrush = QBrush(itsColor);
00046   itsPen   = QPen(QBrush(QColor(0, 0, 0)), 1);
00047   itsPen.setCosmetic(true);
00048 
00049   QGraphicsItem::setZValue(2);
00050 
00051 }
00052 
00053 void AnnotationObjectVertex::makeTransparent()
00054 {
00055   itsBrush = QBrush();
00056   itsPen   = QPen(Qt::NoPen);
00057   QGraphicsItem::setZValue(2);
00058 }
00059 
00060 void AnnotationObjectVertex::makeOpaque()
00061 {
00062   itsPen   = QPen(QBrush(QColor(0,0,0)), 1);
00063   itsPen.setCosmetic(true);
00064   itsBrush = QBrush(itsColor);
00065   QGraphicsItem::setZValue(4);
00066 }
00067 
00068 const QRectF AnnotationObjectVertex::getVertexRect(void) const
00069 {
00070   return itsVertexSize;
00071 }
00072 
00073 
00074 //######################################################################
00075 QRectF AnnotationObjectVertex::boundingRect() const
00076 {
00077   QTransform vp_trans = this->scene()->views()[0]->viewportTransform();
00078 
00079   qreal sx = vp_trans.m11();
00080   qreal sy = vp_trans.m22();
00081 
00082   QRect bbox(itsVertexSize.x()*sx, itsVertexSize.y()*sy, itsVertexSize.width()*sx, itsVertexSize.height()*sy);
00083 
00084   return bbox;
00085 }
00086 
00087 //######################################################################
00088 void AnnotationObjectVertex::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
00089 {
00090   GVX_TRACE(__PRETTY_FUNCTION__);
00091 
00092   painter->setClipRect( option->exposedRect );
00093 
00094   //Draw this vertex as an ellipse
00095   painter->setPen(itsPen);
00096   painter->setBrush(itsBrush);
00097   painter->drawEllipse(this->getVertexRect());
00098 }
00099 
00100 //######################################################################
00101 QVariant AnnotationObjectVertex::itemChange(GraphicsItemChange change, const QVariant &value)
00102 {
00103   //Redraw the parent when this vertex is moved so that the polygon outline
00104   //redraws on the fly
00105   if(change == QGraphicsItem::ItemPositionHasChanged)
00106     itsParent->update();
00107 
00108   return QGraphicsItem::itemChange(change, value);
00109 }
00110 
00111 //######################################################################
00112 void AnnotationObjectVertex::hoverEnterEvent(QGraphicsSceneHoverEvent * event)
00113 {
00114 
00115   if(itsPen.style() != Qt::NoPen)
00116   {
00117     //Make the vertex a bit more opaque when there is a mouseover
00118     itsColor.setAlpha(255);
00119     itsBrush = QBrush(itsColor);
00120     itsPen   = QPen(QBrush(QColor(128, 128, 128)), 3);
00121     itsPen.setCosmetic(true);
00122     update();
00123   }
00124 
00125 }
00126 
00127 //######################################################################
00128 void AnnotationObjectVertex::setKeyframe(int frameNum, QPointF pos, bool visible)
00129 {
00130   itsAnimation->setPosition(frameNum, pos, visible);
00131 }
00132 
00133 //######################################################################
00134 void AnnotationObjectVertex::hoverLeaveEvent(QGraphicsSceneHoverEvent * event)
00135 {
00136 
00137   if(itsPen.style() != Qt::NoPen)
00138   {
00139     //Make the vertex a bit more transparent when there is a mouseover
00140     itsColor.setAlpha(128);
00141     itsBrush = QBrush(itsColor);
00142     itsPen   = QPen(QBrush(QColor(0, 0, 0)), 1);
00143     itsPen.setCosmetic(true);
00144     update();
00145   }
00146 }
00147 
00148 //######################################################################
00149 void AnnotationObjectVertex::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
00150 {
00151   itsParent->pubPrepareGeometryChange();
00152   int currFrame = itsParent->getCurrentFrameNum();
00153 
00154   //Add our current position as a keyframe in the animation if this
00155   //object was moved by the mouse
00156   if(this->pos() != itsAnimation->getFrameState(currFrame).pos)
00157   {
00158     itsAnimation->setPosition(currFrame, pos());
00159     emit(animationChanged());
00160   }
00161 
00162   //Pass the event down to the default event handler
00163   QGraphicsItem::mouseReleaseEvent(event);
00164 }
00165 
00166 //######################################################################
00167 void AnnotationObjectVertex::mousePressEvent(QGraphicsSceneMouseEvent * event)
00168 {
00169   itsParent->selectVertex(this);
00170 
00171   //Pass the event down to the default event handler
00172   QGraphicsItem::mousePressEvent(event);
00173 }
00174 
00175 //######################################################################
00176 void AnnotationObjectVertex::frameChanged(int frameNum)
00177 {
00178   //Store the current frame number
00179   itsCurrentFrame = frameNum;
00180 
00181   //Compute our interpolated position and visibility
00182   ObjectAnimation::FrameState state = itsAnimation->getFrameState(frameNum);
00183 
00184   //Set our position and visibility
00185   QGraphicsItem::setPos(state.pos);
00186   QGraphicsItem::setVisible(state.visible);
00187 
00188   update();
00189 }
00190 
00191 //######################################################################
00192 void AnnotationObjectVertex::clearAnimation()
00193 {
00194   itsAnimation->clear();
00195   emit(animationChanged());
00196 }
00197 
00198 ////////////////////////////////////////////////////////////
00199 
00200 
00201 //######################################################################
00202 AnnotationObject::AnnotationObject(int frameNum, FrameRange frameRange, QPointF initialPos, QString description, int type, QGraphicsItem * parent) :
00203   QGraphicsItem(parent),
00204   itsId(theirIdCount++),
00205   itsDescription(description),
00206   itsType(type),
00207   itsAnimation(new ObjectAnimation(frameNum, frameRange, initialPos)),
00208   itsAnimationModel(this)
00209 {
00210   //Assign a random color to this object
00211   QStringList possibleColors = QColor::colorNames();
00212   itsColor = QColor(possibleColors[qrand()%possibleColors.size()]);
00213 
00214   //Add a square of vertices for the initial shape
00215   this->addVertex(itsVertices.size(), new AnnotationObjectVertex(
00216         this, frameNum, itsAnimation->getFrameRange(), QPointF(-20, -20))
00217       );
00218 
00219   this->addVertex(itsVertices.size(), new AnnotationObjectVertex(
00220         this, frameNum, itsAnimation->getFrameRange(), QPointF(20, -20))
00221       );
00222 
00223   this->addVertex(itsVertices.size(), new AnnotationObjectVertex(
00224         this, frameNum, itsAnimation->getFrameRange(), QPointF(20, 20))
00225       );
00226 
00227   this->addVertex(itsVertices.size(), new AnnotationObjectVertex(
00228         this, frameNum, itsAnimation->getFrameRange(), QPointF(-20, 20))
00229       );
00230 
00231   //Create the initial polygon from these vertices
00232   recalculatePoly();
00233 
00234   //Tell Qt that this item is available for drag & drop
00235   setFlags(QGraphicsItem::ItemIsMovable);
00236 
00237   //Deselect this object
00238   showDeselected();
00239 
00240   //When our animation object changes states, we need to update ourselves
00241   QWidget::connect(itsAnimation, SIGNAL(animationChanged()), &itsAnimationModel, SLOT(animationChanged()));
00242 
00243   QGraphicsItem::setZValue(1);//AnnotationObjectZValue);
00244   itsCurrentFrame = frameNum;
00245 }
00246 
00247 //######################################################################
00248 AnnotationObject::~AnnotationObject()
00249 {
00250   //Destroy all of the child vertices when this object is destroyed
00251   for(int i=0; i<itsVertices.size(); i++)
00252     delete itsVertices[i];
00253 
00254   //Destroy our animation
00255   delete itsAnimation;
00256 }
00257 
00258 //######################################################################
00259 void AnnotationObject::forceId(int id)
00260 {
00261   itsId = id;
00262   if(itsId >= theirIdCount)
00263     theirIdCount = itsId+1;
00264 }
00265 
00266 //######################################################################
00267 void AnnotationObject::addVertex(int index, AnnotationObjectVertex * v)
00268 {
00269   itsAnimationModel.beginInsertRow(index+1);
00270   //Insert this vertex between the two vertices of the closest line
00271   itsVertices.insert(index, v);
00272   itsAnimationModel.endInsertRow();
00273 
00274   //When our animation object changes states, we need to update ourselves
00275   QWidget::connect(v->getAnimation(), SIGNAL(animationChanged()), &itsAnimationModel, SLOT(animationChanged()));
00276 
00277   itsAnimationModel.animationChanged();
00278 }
00279 
00280 //######################################################################
00281 void AnnotationObject::setVertices(std::map<int, ObjectAnimation::FrameState> VertexFrames)
00282 {
00283   //Delete any existing vertices
00284   itsAnimationModel.beginRemoveRowsPub(QModelIndex(), 0, itsVertices.size()); 
00285   for(int i=0; i<itsVertices.size(); i++)
00286   {
00287     delete itsVertices[i];
00288   }
00289   itsVertices.clear();
00290   itsAnimationModel.endRemoveRow();
00291 
00292   std::map<int, ObjectAnimation::FrameState>::iterator vIt;
00293   for(vIt=VertexFrames.begin(); vIt!=VertexFrames.end(); vIt++)
00294   {
00295     QPointF pos = vIt->second.pos;
00296 
00297     AnnotationObjectVertex *newVertex =
00298       new AnnotationObjectVertex(this, itsCurrentFrame, itsAnimation->getFrameRange(), pos);
00299 
00300     //Clear all keyframe from this vertices animation, because we don't yet know where
00301     //its first keyframe is.
00302     newVertex->clearAnimation();
00303 
00304     this->addVertex(vIt->first, newVertex);
00305   }
00306 }
00307 
00308 //######################################################################
00309 void AnnotationObject::insertVertexAtPoint(QPointF point)
00310 {
00311   //Map from the scene coordinate system to our local coordinate system
00312   point = mapFromScene(point);
00313 
00314   //Find the distance from the clicked point to the first line
00315   QLineF line(itsVertices[0]->pos(), itsVertices[1]->pos());
00316   int minDistIdx = 1;
00317   qreal minDist  = distanceToLine(line, point);
00318 
00319   //Find the distance from the clicked point to the middle set of lines
00320   for(int i=2; i<itsVertices.size(); i++)
00321   {
00322     line = QLineF(itsVertices[i-1]->pos(), itsVertices[i]->pos());
00323     qreal dist = distanceToLine(line, point);
00324     if(dist < minDist)
00325     {
00326       minDist = dist;
00327       minDistIdx = i;
00328     }
00329   }
00330 
00331   //Find the distance from the clicked point to the last line
00332   line = QLineF(itsVertices[itsVertices.size()-1]->pos(), itsVertices[0]->pos());
00333   qreal dist = distanceToLine(line, point);
00334   if(dist < minDist)
00335   {
00336     minDist = dist;
00337     minDistIdx = 0;
00338   }
00339 
00340   //Create a new vertex, and drop it onto the clicked point
00341   AnnotationObjectVertex *newVertex = new AnnotationObjectVertex(this, itsCurrentFrame, itsAnimation->getFrameRange(), point);
00342 
00343   this->addVertex(minDistIdx, newVertex);
00344 }
00345 
00346 //######################################################################
00347 void AnnotationObject::removeVertex(QPointF point)
00348 {
00349   //Grab the pointer to the item at the clicked point
00350   QGraphicsItem * item = scene()->itemAt(point);
00351 
00352   //If there is no item there, then there's nothing to do
00353   if(item == NULL) return;
00354 
00355   //If we have only three vertices left, then we can't delete any
00356   if(itsVertices.size() <= 3) return;
00357 
00358   //Find out if the item has the same address as one of our vertices
00359   for(int i=0; i<itsVertices.size(); i++)
00360   {
00361     if( item == itsVertices[i] )
00362     {
00363       itsAnimationModel.beginRemoveRow(i+1);
00364       //If we have found our vertex, then we need to delete it.
00365       itsVertices.removeAt(i);
00366       delete item;
00367       itsAnimationModel.endRemoveRow();
00368       break;
00369     }
00370   }
00371 }
00372 
00373 //######################################################################
00374 QPointF AnnotationObject::getCenter() const
00375 {
00376   //From http://local.wasp.uwa.edu.au/~pbourke/geometry/polyarea/
00377 
00378   float A = 0;
00379   for(int i=0; i<itsVertices.size()-1; i++)
00380   {
00381     A +=
00382       (
00383        itsVertices[i]->pos().x() * itsVertices[i+1]->pos().y() -
00384        itsVertices[i+1]->pos().x() * itsVertices[i]->pos().y()
00385       );
00386   }
00387   A +=
00388     (
00389      itsVertices[itsVertices.size()-1]->pos().x() * itsVertices[0]->pos().y() -
00390      itsVertices[0]->pos().x() * itsVertices[itsVertices.size()-1]->pos().y()
00391     );
00392 
00393   A *= .5;
00394 
00395   float cx = 0;
00396   for(int i=0; i<itsVertices.size()-1; i++)
00397   {
00398     cx +=
00399       (itsVertices[i]->pos().x() + itsVertices[i+1]->pos().x()) *
00400       (
00401        itsVertices[i]->pos().x()*itsVertices[i+1]->pos().y() -
00402        itsVertices[i+1]->pos().x()*itsVertices[i]->pos().y()
00403       );
00404   }
00405   cx +=
00406     (itsVertices[itsVertices.size()-1]->pos().x() + itsVertices[0]->pos().x()) *
00407     (
00408      itsVertices[itsVertices.size()-1]->pos().x()*itsVertices[0]->pos().y() -
00409      itsVertices[0]->pos().x()*itsVertices[itsVertices.size()-1]->pos().y()
00410     );
00411   cx /= 6*A;
00412 
00413   float cy = 0;
00414   for(int i=0; i<itsVertices.size()-1; i++)
00415   {
00416     cy +=
00417       (itsVertices[i]->pos().y() + itsVertices[i+1]->pos().y()) *
00418       (
00419        itsVertices[i]->pos().x()*itsVertices[i+1]->pos().y() -
00420        itsVertices[i+1]->pos().x()*itsVertices[i]->pos().y()
00421       );
00422   }
00423   cy +=
00424     (itsVertices[itsVertices.size()-1]->pos().y() + itsVertices[0]->pos().y()) *
00425     (
00426      itsVertices[itsVertices.size()-1]->pos().x()*itsVertices[0]->pos().y() -
00427      itsVertices[0]->pos().x()*itsVertices[itsVertices.size()-1]->pos().y()
00428     );
00429   cy /= 6*A;
00430 
00431   return QPointF(cx, cy);
00432 }
00433 
00434 //######################################################################
00435 QRectF AnnotationObject::boundingRect() const
00436 {
00437   return itsPoly.boundingRect() | childrenBoundingRect();
00438 }
00439 
00440 //######################################################################
00441 void AnnotationObject::recalculatePoly()
00442 {
00443   GVX_TRACE(__PRETTY_FUNCTION__);
00444 
00445   //Tell Qt that we are about to change the shape of this object
00446 
00447   //Construct our polygon from our vertices which are stored in clockwise order
00448   QPolygonF poly;
00449   for(int i=0; i<itsVertices.size(); i++)
00450   {
00451     if(itsVertices[i]->getFrameState(itsCurrentFrame).visible)
00452       poly.append(itsVertices[i]->pos());
00453   }
00454   itsPoly = poly;
00455 }
00456 
00457 //######################################################################
00458 void AnnotationObject::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
00459 {
00460   GVX_TRACE(__PRETTY_FUNCTION__);
00461 
00462   //Recalculate the polygon on a paint, because it's likely we got here from an update() which was called
00463   //when something was changed
00464   recalculatePoly();
00465   painter->setClipRect( option->exposedRect );
00466 
00467   if(itsSelected)
00468   {
00469     //Make the polygon a bit more opaque when selected
00470     itsColor.setAlpha(128);
00471     itsBrush = QBrush(itsColor);
00472     itsPen = QPen(QBrush(QColor(255,255,255)), 2, Qt::SolidLine, Qt::RoundCap);
00473     itsPen.setCosmetic(true);
00474   }
00475   else
00476   {
00477     //Make the polygon a bit more transparent when deselected
00478     itsColor.setAlpha(int(float(itsOpacity)/100.0*255.0));
00479     itsBrush = QBrush(itsColor);
00480     itsPen   = QPen(Qt::NoPen);
00481   }
00482 
00483   //Draw this object as a colored polygon with a thick border
00484   painter->setPen(itsPen);
00485   painter->setBrush(itsBrush);
00486   painter->drawPolygon(itsPoly);
00487 }
00488 
00489 //######################################################################
00490 void AnnotationObject::showSelected()
00491 {
00492   itsSelected = true;
00493 
00494   for(int i=0; i<itsVertices.size(); i++)
00495     itsVertices[i]->makeOpaque();
00496 
00497   //Bring this object to the front so we can be sure to edit it
00498   QGraphicsItem::setZValue(3);
00499 
00500   update();
00501 }
00502 
00503 //######################################################################
00504 void AnnotationObject::showDeselected()
00505 {
00506   itsSelected = false;
00507 
00508   for(int i=0; i<itsVertices.size(); i++)
00509     itsVertices[i]->makeTransparent();
00510 
00511   QGraphicsItem::setZValue(1);
00512   update();
00513 }
00514 
00515 //######################################################################
00516 void AnnotationObject::frameChanged(int frameNum)
00517 {
00518   GVX_TRACE(__PRETTY_FUNCTION__);
00519 
00520   //Store the current frame number
00521   itsCurrentFrame = frameNum;
00522 
00523   //Compute our interpolated position and visibility
00524   ObjectAnimation::FrameState state = itsAnimation->getFrameState(frameNum);
00525 
00526   //Set our position and visibility
00527   QGraphicsItem::setPos(state.pos);
00528   QGraphicsItem::setVisible(state.visible);
00529 
00530 
00531   if(state.visible)
00532   {
00533     for(int i=0; i<itsVertices.size(); i++)
00534       itsVertices[i]->frameChanged(frameNum);
00535   }
00536 
00537   itsAnimationModel.animationChanged();
00538 
00539   update();
00540 }
00541 
00542 void AnnotationObject::setKeyframe(int frameNum, QPointF pos, bool visible)
00543 {
00544   itsAnimation->setPosition(frameNum, pos, visible);
00545 }
00546 
00547 //######################################################################
00548 void AnnotationObject::updateAnimation()
00549 {
00550   frameChanged(itsCurrentFrame);
00551 }
00552 
00553 //######################################################################
00554 void AnnotationObject::mouseReleaseEvent(QGraphicsSceneMouseEvent * event)
00555 {
00556   //Add our current position as a keyframe in the animation if this
00557   //object was moved by the mouse
00558   if(this->pos() != itsAnimation->getFrameState(itsCurrentFrame).pos)
00559   {
00560                 for(int i=0; i<itsVertices.size(); ++i)
00561                 {
00562                         ObjectAnimation::FrameState vertState = itsVertices[i]->getFrameState(itsCurrentFrame);
00563                         itsVertices[i]->setKeyframe(itsCurrentFrame, vertState.pos, vertState.visible);
00564                 }
00565 
00566     itsAnimation->setPosition(itsCurrentFrame, pos());
00567     emit(animationChanged(0, itsCurrentFrame));
00568   }
00569 
00570   //Pass the event down to the default event handler
00571   QGraphicsItem::mouseReleaseEvent(event);
00572 }
00573 
00574 //######################################################################
00575 void AnnotationObject::mousePressEvent(QGraphicsSceneMouseEvent * event)
00576 {
00577   //Let everyone know that we were selected
00578   emit(objectSelected(itsId));
00579 
00580   //Let the animation view know that the main object was selected
00581   emit(rowSelected(0));
00582 
00583   itsAnimationModel.animationChanged();
00584 
00585   //Pass the event down to the default event handler
00586 }
00587 
00588 
00589 void AnnotationObject::constructAnimationContextMenu(QPoint globalPos, int row, int column)
00590 {
00591   if(row == 0)
00592   {
00593     //Tell the animation object to construct a context menu, and perform the requisite action
00594     itsAnimation->constructContextMenu(globalPos, column);
00595 
00596     //Recompute our object's position with the current frame in case something was changed
00597     //in our animation
00598     frameChanged(itsCurrentFrame);
00599   }
00600   else
00601   {
00602     itsVertices[row-1]->getAnimation()->constructContextMenu(globalPos, column);
00603   }
00604   //Repaint ourselves
00605   update();
00606 }
00607 
00608 
00609 //######################################################################
00610 AnimationModel* AnnotationObject::getAnimationModel()
00611 {
00612   return &itsAnimationModel;
00613 }
00614 
00615 
00616 //######################################################################
00617 void AnnotationObject::selectVertex(AnnotationObjectVertex * vertex)
00618 {
00619   GVX_TRACE(__PRETTY_FUNCTION__);
00620 
00621   //Find which row contains the given vertex
00622   int row=-1;
00623   for(int i=0; i<itsVertices.size(); i++)
00624   {
00625     if(itsVertices[i] == vertex)
00626     {
00627       row = i;
00628       break;
00629     }
00630   }
00631   ASSERT(row >= 0);
00632 
00633   row = row+1;
00634 
00635   //Let everyone know that we were selected
00636   emit(objectSelected(itsId));
00637 
00638   //Let the animation view know that this particular vertex was selected
00639   emit(rowSelected(row));
00640 
00641   //Tell the model to tell the view to refresh the whole table
00642   itsAnimationModel.animationChanged();
00643 }
00644 
00645 //######################################################################
00646 QPainterPath AnnotationObject::shape() const
00647 {
00648   QPainterPath path;
00649   path.addPolygon(itsPoly);
00650   return path;
00651 }
00652 
00653 //######################################################################
00654 QVector<QMap<int, QPointF> > AnnotationObject::renderAnimation()
00655 {
00656   //Create an empty set of frame/position mappings for each of our vertices
00657   QVector<QMap<int, QPointF> > vertexAnimations(itsVertices.size());
00658 
00659   for(int fnum=itsAnimation->getFrameRange().getFirst(); fnum<itsAnimation->getFrameRange().getLast(); ++fnum)
00660   {
00661     ObjectAnimation::FrameState parentState = itsAnimation->getFrameState(fnum);
00662     if(parentState.visible)
00663     {
00664       //Loop through each vertex for this frame, and render out the position
00665       for(int vIdx=0; vIdx<itsVertices.size(); ++vIdx)
00666       {
00667         ObjectAnimation::FrameState vertexState = itsVertices[vIdx]->getFrameState(fnum);
00668         
00669         if(vertexState.visible)
00670         {
00671           vertexAnimations[vIdx][fnum] = vertexState.pos + parentState.pos;
00672         }
00673       }
00674     }
00675   }
00676   return vertexAnimations;
00677 }
00678 
00679 //######################################################################
00680 std::map<int, ObjectAnimation::FrameState> AnnotationObject::getVertexStates(int fnum)
00681 {
00682   std::map<int, ObjectAnimation::FrameState> vertexStates;
00683 
00684   ObjectAnimation::FrameState objState = this->itsAnimation->getFrameState(fnum);
00685 
00686 
00687   for(int vIdx=0; vIdx<itsVertices.size(); ++vIdx)
00688   {
00689     ObjectAnimation::FrameState vState = itsVertices[vIdx]->getFrameState(fnum);
00690 
00691     //Ensure that if the object is invisible, then all of its vertices are as well
00692     //if(!objState.visible)
00693     //  vState.visible = false;
00694 
00695     vState.pos = vState.pos + objState.pos;
00696 
00697     vertexStates[vIdx] = vState;
00698   }
00699 
00700   return vertexStates;
00701 }
00702 
00703 //######################################################################
00704 void AnnotationObject::clearAnimation()
00705 {
00706   itsAnimation->clear();
00707 }
00708 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723 
00724 
00725 
00726 
00727 //######################################################################
00728 qreal distanceToLine(QLineF line, QPointF point)
00729 {
00730   //From http://www.codeguru.com/forum/showthread.php?t=194400
00731   qreal distanceLine = 0;
00732   qreal distanceSegment = 0;
00733 
00734   double r_numerator = (point.x()-line.x1())*(line.x2()-line.x1()) + (point.y()-line.y1())*(line.y2()-line.y1());
00735   double r_denomenator = (line.x2()-line.x1())*(line.x2()-line.x1()) + (line.y2()-line.y1())*(line.y2()-line.y1());
00736   double r = r_numerator / r_denomenator;
00737   //
00738   //FIXME: UNUSED? double px = line.x1() + r*(line.x2()-line.x1());
00739   //double py = line.y1() + r*(line.y2()-line.y1());
00740   //
00741   double s =  ((line.y1()-point.y())*(line.x2()-line.x1())-(line.x1()-point.x())*(line.y2()-line.y1()) ) / r_denomenator;
00742 
00743   distanceLine = fabs(s)*sqrt(r_denomenator);
00744 
00745   //
00746   // (xx,yy) is the point on the lineSegment closest to (point.x(),point.y())
00747   //
00748   //FIXME: UNUSED? double xx = px;
00749   //double yy = py;
00750 
00751   if ( (r >= 0) && (r <= 1) )
00752   {
00753     distanceSegment = distanceLine;
00754   }
00755   else
00756   {
00757 
00758 
00759     double dist1 = (point.x()-line.x1())*(point.x()-line.x1()) + (point.y()-line.y1())*(point.y()-line.y1());
00760     double dist2 = (point.x()-line.x2())*(point.x()-line.x2()) + (point.y()-line.y2())*(point.y()-line.y2());
00761     if (dist1 < dist2)
00762     {
00763       //xx = line.x1();
00764       //yy = line.y1();
00765       distanceSegment = sqrt(dist1);
00766     }
00767     else
00768     {
00769       //xx = line.x2();
00770       //yy = line.y2();
00771       distanceSegment = sqrt(dist2);
00772     }
00773 
00774 
00775   }
00776 
00777   return distanceSegment;
00778 }
00779 
00780 #endif //ANNOTATIONOBJECT_QT_C
Generated on Sun May 8 08:41:02 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3