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