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
00026
00027 setFlags(
00028 QGraphicsItem::ItemIsMovable |
00029 QGraphicsItem::ItemIgnoresTransformations |
00030 QGraphicsItem::ItemSendsGeometryChanges
00031 );
00032
00033 setPos(initialPos);
00034
00035
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
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
00104
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
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
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
00155
00156 if(this->pos() != itsAnimation->getFrameState(currFrame).pos)
00157 {
00158 itsAnimation->setPosition(currFrame, pos());
00159 emit(animationChanged());
00160 }
00161
00162
00163 QGraphicsItem::mouseReleaseEvent(event);
00164 }
00165
00166
00167 void AnnotationObjectVertex::mousePressEvent(QGraphicsSceneMouseEvent * event)
00168 {
00169 itsParent->selectVertex(this);
00170
00171
00172 QGraphicsItem::mousePressEvent(event);
00173 }
00174
00175
00176 void AnnotationObjectVertex::frameChanged(int frameNum)
00177 {
00178
00179 itsCurrentFrame = frameNum;
00180
00181
00182 ObjectAnimation::FrameState state = itsAnimation->getFrameState(frameNum);
00183
00184
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
00211 QStringList possibleColors = QColor::colorNames();
00212 itsColor = QColor(possibleColors[qrand()%possibleColors.size()]);
00213
00214
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
00232 recalculatePoly();
00233
00234
00235 setFlags(QGraphicsItem::ItemIsMovable);
00236
00237
00238 showDeselected();
00239
00240
00241 QWidget::connect(itsAnimation, SIGNAL(animationChanged()), &itsAnimationModel, SLOT(animationChanged()));
00242
00243 QGraphicsItem::setZValue(1);
00244 itsCurrentFrame = frameNum;
00245 }
00246
00247
00248 AnnotationObject::~AnnotationObject()
00249 {
00250
00251 for(int i=0; i<itsVertices.size(); i++)
00252 delete itsVertices[i];
00253
00254
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
00271 itsVertices.insert(index, v);
00272 itsAnimationModel.endInsertRow();
00273
00274
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
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
00301
00302 newVertex->clearAnimation();
00303
00304 this->addVertex(vIt->first, newVertex);
00305 }
00306 }
00307
00308
00309 void AnnotationObject::insertVertexAtPoint(QPointF point)
00310 {
00311
00312 point = mapFromScene(point);
00313
00314
00315 QLineF line(itsVertices[0]->pos(), itsVertices[1]->pos());
00316 int minDistIdx = 1;
00317 qreal minDist = distanceToLine(line, point);
00318
00319
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
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
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
00350 QGraphicsItem * item = scene()->itemAt(point);
00351
00352
00353 if(item == NULL) return;
00354
00355
00356 if(itsVertices.size() <= 3) return;
00357
00358
00359 for(int i=0; i<itsVertices.size(); i++)
00360 {
00361 if( item == itsVertices[i] )
00362 {
00363 itsAnimationModel.beginRemoveRow(i+1);
00364
00365 itsVertices.removeAt(i);
00366 delete item;
00367 itsAnimationModel.endRemoveRow();
00368 break;
00369 }
00370 }
00371 }
00372
00373
00374 QPointF AnnotationObject::getCenter() const
00375 {
00376
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
00446
00447
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
00463
00464 recalculatePoly();
00465 painter->setClipRect( option->exposedRect );
00466
00467 if(itsSelected)
00468 {
00469
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
00478 itsColor.setAlpha(int(float(itsOpacity)/100.0*255.0));
00479 itsBrush = QBrush(itsColor);
00480 itsPen = QPen(Qt::NoPen);
00481 }
00482
00483
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
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
00521 itsCurrentFrame = frameNum;
00522
00523
00524 ObjectAnimation::FrameState state = itsAnimation->getFrameState(frameNum);
00525
00526
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
00557
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
00571 QGraphicsItem::mouseReleaseEvent(event);
00572 }
00573
00574
00575 void AnnotationObject::mousePressEvent(QGraphicsSceneMouseEvent * event)
00576 {
00577
00578 emit(objectSelected(itsId));
00579
00580
00581 emit(rowSelected(0));
00582
00583 itsAnimationModel.animationChanged();
00584
00585
00586 }
00587
00588
00589 void AnnotationObject::constructAnimationContextMenu(QPoint globalPos, int row, int column)
00590 {
00591 if(row == 0)
00592 {
00593
00594 itsAnimation->constructContextMenu(globalPos, column);
00595
00596
00597
00598 frameChanged(itsCurrentFrame);
00599 }
00600 else
00601 {
00602 itsVertices[row-1]->getAnimation()->constructContextMenu(globalPos, column);
00603 }
00604
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
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
00636 emit(objectSelected(itsId));
00637
00638
00639 emit(rowSelected(row));
00640
00641
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
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
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
00692
00693
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
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
00739
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
00747
00748
00749
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
00764
00765 distanceSegment = sqrt(dist1);
00766 }
00767 else
00768 {
00769
00770
00771 distanceSegment = sqrt(dist2);
00772 }
00773
00774
00775 }
00776
00777 return distanceSegment;
00778 }
00779
00780 #endif //ANNOTATIONOBJECT_QT_C