ImageHolder.cpp 22 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. /*
  2. * ImageHolder.cpp
  3. *
  4. * Created on: Oct 5, 2011
  5. * Author: gapchich
  6. */
  7. #include "ImageHolder.h"
  8. #include "functions.h"
  9. #include <QKeyEvent>
  10. #include <QMouseEvent>
  11. #include <QPainter>
  12. #include <QListWidgetItem>
  13. #include <qmath.h>
  14. #include <QDebug>
  15. //! A constructor initializing some variables
  16. ImageHolder::ImageHolder(QWidget *aParent)
  17. : QLabel(aParent)
  18. {
  19. repaint_needed_ = 0;
  20. tool_ = NoTool;
  21. state_ = StandBy;
  22. keyboard_modifier_ = Qt::NoModifier;
  23. focused_selection_ = -1;
  24. focused_selection_type_ = NoFigure;
  25. hovered_point_.figure = NoFigure;
  26. hovered_point_.figureID = -1;
  27. hovered_point_.pointID = -1;
  28. selected_point_ = -1;
  29. list_bounding_box_ = 0;
  30. main_label_ = 0;
  31. //list_bounding_box_ = new QList< QRect >;
  32. scale_ = 1;
  33. point_radius_ = 6;
  34. setScaledContents(true);
  35. setMouseTracking(true);
  36. }
  37. //! An empty destructor
  38. ImageHolder::~ImageHolder()
  39. {
  40. }
  41. //! An event which being automatically called after any change of the widget
  42. /*!
  43. * \see drawBoundingBoxes(QPainter *aPainter, QPen *aPen)
  44. * \see drawPolygons(QPainter *aPainter, QPen *aPen)
  45. *
  46. * It contains drawing of the confirmed and not confirmed selections either.
  47. */
  48. void
  49. ImageHolder::paintEvent(QPaintEvent *anEvent)
  50. {
  51. QLabel::paintEvent(anEvent);
  52. QPainter painter(this);
  53. painter.setRenderHint(QPainter::Antialiasing);
  54. //painter.setRenderHint(QPainter::SmoothPixmapTransform);
  55. QPen pen;
  56. if (NoTool != tool_) {
  57. pen.setWidth(1);
  58. pen.setColor(QColor(Qt::black));
  59. pen.setStyle(Qt::DashLine);
  60. painter.setPen(pen);
  61. if (BoundingBoxTool == tool_) {
  62. /* scaling */
  63. QRect bbox = bounding_box_.rect;
  64. QPoint bboxTopLeft = bbox.topLeft() * scale_;
  65. QPoint bboxBottomRight = bbox.bottomRight() * scale_;
  66. bbox.setTopLeft(bboxTopLeft);
  67. bbox.setBottomRight(bboxBottomRight);
  68. painter.drawRect(bbox);
  69. }
  70. else if (PolygonTool == tool_) {
  71. /* scaling */
  72. QPoint point;
  73. QPolygon poly = polygon_.poly;
  74. for (int i = 0; i < poly.size(); i++) {
  75. point.setX(poly.at(i).x());
  76. point.setY(poly.at(i).y());
  77. point *= scale_;
  78. poly.remove(i);
  79. poly.insert(i, point);
  80. }
  81. painter.drawPolygon(poly);
  82. }
  83. }
  84. /* drawing bounding boxes */
  85. drawBoundingBoxes(&painter, &pen);
  86. drawPolygons(&painter, &pen);
  87. }
  88. //! draws only confirmed bounding boxes
  89. /*!
  90. * parameters of bboxes may vary depending on whether bbox is selected or not or
  91. * whether it's label is main or not.
  92. */
  93. void
  94. ImageHolder::drawBoundingBoxes(
  95. QPainter *aPainter,
  96. QPen *aPen
  97. ) const
  98. {
  99. if (0 == list_bounding_box_)
  100. {
  101. return;
  102. /* NOTREACHED */
  103. }
  104. Qt::PenStyle penStyle;
  105. /* default width is hardcoded */
  106. int width = 2;
  107. /* drawing all the bboxes */
  108. for (int i = 0; i < list_bounding_box_->size(); i++) {
  109. penStyle = Qt::SolidLine;
  110. int labelID = list_bounding_box_->at(i)->label_ID_;
  111. /* setting color for the label of current bbox */
  112. if (labelID < list_label_color_->count())
  113. aPen->setColor(QColor(list_label_color_->at(labelID)));
  114. /* in case there is no color for such label */
  115. else
  116. aPen->setColor(QColor(Qt::white));
  117. /* checking whether labeled area is of main label or not */
  118. if (labelID == *main_label_)
  119. width = 3;
  120. else
  121. width = 2;
  122. /* changing the line style and width if current area is selected(focused) */
  123. if (RectFigure == focused_selection_type_ &&
  124. focused_selection_ == i) {
  125. penStyle = Qt::DotLine;
  126. width = 3;
  127. }
  128. /* scaling */
  129. QRect rect = list_bounding_box_->at(i)->rect.normalized();
  130. QPoint topLeft = rect.topLeft() * scale_;
  131. QPoint bottomRight = rect.bottomRight() * scale_;
  132. rect.setTopLeft(topLeft);
  133. rect.setBottomRight(bottomRight);
  134. if (focused_selection_ == i &&
  135. focused_selection_type_ == RectFigure) {
  136. QPen circPen;
  137. circPen.setWidth(2);
  138. circPen.setStyle(Qt::SolidLine);
  139. circPen.setColor(aPen->color());
  140. aPainter->setPen(circPen);
  141. for (int j = 0; j < 4; j++) {
  142. QPoint point;
  143. /* getting the number of point mouse pointer hovered on */
  144. if (!j) {
  145. point = rect.topLeft();
  146. }
  147. else if (1 == j)
  148. {
  149. point = rect.topRight();
  150. }
  151. else if (2 == j)
  152. {
  153. point = rect.bottomRight();
  154. }
  155. else if (3 == j)
  156. {
  157. point = rect.bottomLeft();
  158. }
  159. /* if current point is hovered then fill it */
  160. if (i == hovered_point_.figureID &&
  161. j == hovered_point_.pointID &&
  162. RectFigure == hovered_point_.figure) {
  163. QBrush brush;
  164. brush.setColor(aPen->color());
  165. brush.setStyle(Qt::SolidPattern);
  166. aPainter->setBrush(brush);
  167. }
  168. aPainter->drawEllipse(point, point_radius_, point_radius_);
  169. aPainter->setBrush(Qt::NoBrush);
  170. }
  171. }
  172. aPen->setWidth(width);
  173. aPen->setStyle(penStyle);
  174. aPainter->setPen(*aPen);
  175. aPainter->drawRect(rect);
  176. /* drawing label ids of these boxes */
  177. QString labelIDText =
  178. QString("%1").arg(labelID);
  179. aPainter->drawText(
  180. rect.left() + 5,
  181. rect.top() + 5,
  182. 20,
  183. 20,
  184. Qt::AlignLeft,
  185. labelIDText
  186. );
  187. }
  188. }
  189. //! draws only confirmed polygons
  190. /*!
  191. * parameters of polygons may vary depending on whether poly is selected or not or
  192. * whether it's label is main or not.
  193. */
  194. void
  195. ImageHolder::drawPolygons(
  196. QPainter *aPainter,
  197. QPen *aPen
  198. ) const
  199. {
  200. if (0 == list_polygon_)
  201. {
  202. return;
  203. /* NOTREACHED */
  204. }
  205. Qt::PenStyle penStyle = Qt::SolidLine;
  206. /* default width is hardcoded */
  207. int width = 2;
  208. /* drawing all the polygons */
  209. for (int i = 0; i < list_polygon_->size(); i++) {
  210. penStyle = Qt::SolidLine;
  211. int labelID = list_polygon_->at(i)->label_ID_;
  212. /* setting color for the label of current bbox */
  213. if (labelID < list_label_color_->count())
  214. aPen->setColor(QColor(list_label_color_->at(labelID)));
  215. /* in case there is no color for such label */
  216. else
  217. aPen->setColor(QColor(Qt::white));
  218. /* checking whether labeled area is of main object or not */
  219. if (labelID == *main_label_)
  220. width = 3;
  221. else
  222. width = 2;
  223. /* changing the line style and width if current area is selected(focused) */
  224. if (PolyFigure == focused_selection_type_ &&
  225. focused_selection_ == i) {
  226. penStyle = Qt::DotLine;
  227. width = 3;
  228. }
  229. QPoint point;
  230. QPolygon poly = list_polygon_->at(i)->poly;
  231. for (int j = 0; j < poly.size(); j++) {
  232. point.setX(poly.at(j).x());
  233. point.setY(poly.at(j).y());
  234. /* scaling */
  235. point *= scale_;
  236. poly.remove(j);
  237. poly.insert(j, point);
  238. /* in case if it's focused */
  239. if (focused_selection_ == i &&
  240. focused_selection_type_ == PolyFigure) {
  241. QPen circPen;
  242. circPen.setWidth(2);
  243. circPen.setStyle(Qt::SolidLine);
  244. circPen.setColor(aPen->color());
  245. aPainter->setPen(circPen);
  246. /* filling the point if it is hovered */
  247. if ((j == hovered_point_.pointID &&
  248. i == hovered_point_.figureID &&
  249. PolyFigure == hovered_point_.figure) ||
  250. j == selected_point_) {
  251. QBrush brush;
  252. brush.setColor(aPen->color());
  253. brush.setStyle(Qt::SolidPattern);
  254. aPainter->setBrush(brush);
  255. }
  256. aPainter->drawEllipse(point, point_radius_, point_radius_);
  257. aPainter->setBrush(Qt::NoBrush);
  258. }
  259. }
  260. aPen->setWidth(width);
  261. aPen->setStyle(penStyle);
  262. aPainter->setPen(*aPen);
  263. aPainter->drawPolygon(poly);
  264. /* drawing label IDs of these polygons */
  265. QString labelIDText =
  266. QString("%1").arg(labelID);
  267. QRect rect = poly.boundingRect();
  268. int x = rect.center().x();
  269. int y = rect.center().y();
  270. aPainter->drawText(
  271. x,
  272. y,
  273. 20,
  274. 20,
  275. Qt::AlignHCenter,
  276. labelIDText
  277. );
  278. }
  279. }
  280. //! Changes current state and setting new coordinates for the bbox
  281. /*!
  282. * \see mouseMoveEvent(QMouseEvent *anEvent)
  283. * \param[in] aNewPos a second point for the bbox(rect)
  284. * \param[in] anOldPos a first point for the bbox
  285. * \param[in,out] aNewRect a pointer to the rectangle
  286. * which is being currently changed
  287. */
  288. void
  289. ImageHolder::triggerBoundBox(
  290. const QPoint &aNewPos,
  291. const QPoint &anOldPos,
  292. QRect *aNewRect
  293. )
  294. {
  295. aNewRect->setCoords(
  296. anOldPos.x(),
  297. anOldPos.y(),
  298. aNewPos.x(),
  299. aNewPos.y()
  300. );
  301. state_ = NewSelection;
  302. repaint_needed_ = 1;
  303. }
  304. //! \brief Changes current state and adding a new point to the
  305. //! current not confirmed polygon
  306. /*!
  307. * \see mouseMoveEvent(QMouseEvent *anEvent)
  308. * \param[in] aPoint a point going to be added to the polygon
  309. * \param[in,out] aNewPoly a pointer to the polygon
  310. * which is being currently changed
  311. */
  312. void
  313. ImageHolder::triggerPolygon(
  314. const QPoint &aPoint,
  315. QPolygon *aNewPoly
  316. )
  317. {
  318. *aNewPoly << aPoint;
  319. repaint_needed_ = 1;
  320. }
  321. //! \brief Puts focus on some of the selections(selected areas)
  322. /*!
  323. * \param[in] anItem should be a pointer to the item of list_areas_ which
  324. * has a string with certain format
  325. * \see ImageLabeler::addPoly(Polygon *poly)
  326. * \see ImageLabeler::list_areas_
  327. * \see focused_selection_
  328. * \see focused_selection_type_
  329. * Parses the string from anItem and gets the selected object out of it
  330. */
  331. void
  332. ImageHolder::focusOnArea(QListWidgetItem *anItem)
  333. {
  334. QString text = anItem->text();
  335. Tool tool = NoTool;
  336. if (-1 != text.indexOf("BBox"))
  337. tool = BoundingBoxTool;
  338. else if (-1 != text.indexOf("Poly"))
  339. tool = PolygonTool;
  340. /* looking for a number of selected area */
  341. if (NoTool != tool) {
  342. bool ok = 0;
  343. focused_selection_ = getNumFromString(&text, "#", ";", &ok);
  344. if (!ok) {
  345. focused_selection_ = -1;
  346. focused_selection_type_ = NoFigure;
  347. return;
  348. /* NOTREACHED */
  349. }
  350. switch (tool) {
  351. case BoundingBoxTool:
  352. focused_selection_type_ = RectFigure;
  353. break;
  354. case PolygonTool:
  355. focused_selection_type_ = PolyFigure;
  356. break;
  357. default:
  358. focused_selection_type_ = NoFigure;
  359. break;
  360. }
  361. }
  362. update();
  363. }
  364. //! Changes scale_ variable depending on zoom direction and scale factor
  365. /*!
  366. * \param[in] aDirection an enum indicating the zoom direction
  367. * \param[in] scaleFactor a speed of zooming
  368. */
  369. void
  370. ImageHolder::scaleImage(
  371. ZoomDirection aDirection,
  372. double scaleFactor
  373. )
  374. {
  375. QSize size = this->size();
  376. /* zoomin */
  377. if (ZoomIn == aDirection) {
  378. size *= scaleFactor;
  379. scale_ *= scaleFactor;
  380. }
  381. /* zoomout */
  382. else if (ZoomOut == aDirection) {
  383. size /= scaleFactor;
  384. scale_ /= scaleFactor;
  385. }
  386. this->resize(size);
  387. }
  388. //! Removes the focus on an object
  389. /*!
  390. * \see paintEvent(QPaintEvent *)
  391. */
  392. void
  393. ImageHolder::clearFocusOnArea()
  394. {
  395. focused_selection_ = -1;
  396. focused_selection_type_ = NoFigure;
  397. }
  398. //! Clears the data of hovered_point_
  399. void
  400. ImageHolder::clearHoveredPoint()
  401. {
  402. hovered_point_.figure = NoFigure;
  403. hovered_point_.figureID = -1;
  404. hovered_point_.pointID = -1;
  405. }
  406. //! Sets current tool
  407. void
  408. ImageHolder::setTool(Tool aTool)
  409. {
  410. switch(aTool) {
  411. case BoundingBoxTool:
  412. tool_ = BoundingBoxTool;
  413. break;
  414. case PolygonTool:
  415. tool_ = PolygonTool;
  416. break;
  417. default:
  418. tool_ = NoTool;
  419. break;
  420. }
  421. }
  422. //! Sets a pointer on the ImageLabeler::list_bounding_box_
  423. void
  424. ImageHolder::setBoundingBoxList(QList< BoundingBox * > *aBBoxList)
  425. {
  426. if (0 == aBBoxList) {
  427. return;
  428. /* NOTREACHED */
  429. }
  430. list_bounding_box_ = aBBoxList;
  431. }
  432. //! Sets a pointer on the ImageLabeler::list_polygon_
  433. void
  434. ImageHolder::setPolygonList(QList< Polygon * > *aPolygonList)
  435. {
  436. if (0 == aPolygonList) {
  437. return;
  438. /* NOTREACHED */
  439. }
  440. list_polygon_ = aPolygonList;
  441. }
  442. //! Sets a pointer on the ImageLabeler::list_label_color
  443. void
  444. ImageHolder::setLabelColorList(QList< uint > *aLabelColorList)
  445. {
  446. if (0 == aLabelColorList) {
  447. return;
  448. /* NOTREACHED */
  449. }
  450. list_label_color_ = aLabelColorList;
  451. }
  452. //! Sets a pointer on the ImageLabeler::main_label_
  453. void
  454. ImageHolder::setMainLabelNum(int *aNum)
  455. {
  456. if (0 == aNum) {
  457. return;
  458. /* NOTREACHED */
  459. }
  460. main_label_ = aNum;
  461. }
  462. //! Sets a pointer on the ImageLabeler::image_
  463. void
  464. ImageHolder::setImage(QPixmap *anImage)
  465. {
  466. if (0 == anImage) {
  467. return;
  468. /* NOTREACHED */
  469. }
  470. image_ = anImage;
  471. }
  472. //! Clears scale, state, bounding_box_ and polygon_
  473. void
  474. ImageHolder::clearAll()
  475. {
  476. //list_bounding_box_->clear();
  477. bounding_box_.rect.setRect(-1, -1, 0, 0);
  478. //list_polygon_->clear();
  479. polygon_.poly.clear();
  480. clearFocusOnArea();
  481. state_ = StandBy;
  482. scale_ = 1;
  483. update();
  484. }
  485. //! Clears las selection(selected area)
  486. void
  487. ImageHolder::clearLast()
  488. {
  489. switch (tool_) {
  490. case BoundingBoxTool:
  491. bounding_box_.rect.setRect(-1, -1, 0, 0);
  492. break;
  493. case PolygonTool:
  494. polygon_.poly.clear();
  495. break;
  496. default:
  497. break;
  498. }
  499. bounding_box_.rect.setRect(-1, -1, 0, 0);
  500. state_ = StandBy;
  501. update();
  502. }
  503. //! Moves bounding_box_ or polygon_ to the corresponding list
  504. /*!
  505. * \see ImageLabeler::confirmSelection()
  506. */
  507. void
  508. ImageHolder::confirmSelection()
  509. {
  510. if (NewSelection != state_ || NoTool == tool_) {
  511. return;
  512. /* NOTREACHED */
  513. }
  514. if (BoundingBoxTool == tool_) {
  515. BoundingBox *bbox = new BoundingBox;
  516. bounding_box_.rect = bounding_box_.rect.normalized();
  517. *bbox = bounding_box_;
  518. list_bounding_box_->append(bbox);
  519. bounding_box_.rect.setRect(-1, -1, 0, 0);
  520. }
  521. else if (PolygonTool == tool_) {
  522. Polygon *poly = new Polygon;
  523. *poly = polygon_;
  524. list_polygon_->append(poly);
  525. polygon_.poly.clear();
  526. }
  527. list_poly_history_.clear();
  528. state_ = StandBy;
  529. update();
  530. }
  531. //! returns state
  532. ImageHolder::State
  533. ImageHolder::state() const
  534. {
  535. return state_;
  536. }
  537. //! returns tool
  538. ImageHolder::Tool
  539. ImageHolder::tool() const
  540. {
  541. return tool_;
  542. }
  543. //! returns focused_selection_
  544. int
  545. ImageHolder::focusedSelection() const
  546. {
  547. return focused_selection_;
  548. }
  549. //! returns focused_selection_type_
  550. Figure
  551. ImageHolder::focusedSelectionType() const
  552. {
  553. return focused_selection_type_;
  554. }
  555. //! removes last added point form the polygon_
  556. void
  557. ImageHolder::undo()
  558. {
  559. if (PolygonTool == tool_ &&
  560. NewSelection == state_ &&
  561. !polygon_.poly.isEmpty())
  562. {
  563. list_poly_history_.append(polygon_.poly.last());
  564. polygon_.poly.pop_back();
  565. repaint_needed_ = 1;
  566. }
  567. if (repaint_needed_) {
  568. update();
  569. repaint_needed_ = 0;
  570. }
  571. }
  572. //! Brings back the last removed by undo() point
  573. void
  574. ImageHolder::redo()
  575. {
  576. if (PolygonTool == tool_ &&
  577. NewSelection == state_ &&
  578. !list_poly_history_.isEmpty())
  579. {
  580. polygon_.poly.append(list_poly_history_.last());
  581. list_poly_history_.pop_back();
  582. repaint_needed_ = 1;
  583. }
  584. if (repaint_needed_) {
  585. update();
  586. repaint_needed_ = 0;
  587. }
  588. }
  589. //! Checks whether mouse pointer is on some point of any object or not
  590. /*!
  591. * \see hovered_point_
  592. * \see drawBoundingBoxes(QPainter *aPainter, QPen *aPen)
  593. * \see drawPolygons(QPainter *aPainter, QPen *aPen)
  594. *
  595. * It simply checks all the points of all objects if mouse
  596. * pointer is hovered above any of them
  597. */
  598. void
  599. ImageHolder::checkForPoints(QPoint *aPos)
  600. {
  601. if ((!list_polygon_->count() &&
  602. !list_bounding_box_->count()) ||
  603. !aPos) {
  604. return;
  605. /* NOTREACHED */
  606. }
  607. int newRadius = 0;
  608. int x = aPos->x();
  609. int y = aPos->y();
  610. /* center coordinates */
  611. int xc = 0;
  612. int yc = 0;
  613. for (int i = 0; i < list_polygon_->count(); i++) {
  614. QPolygon poly = list_polygon_->at(i)->poly;
  615. for (int j = 0; j < poly.count(); j++) {
  616. xc = poly.at(j).x();
  617. yc = poly.at(j).y();
  618. newRadius = qSqrt(qPow(x - xc, 2) + qPow(y - yc, 2));
  619. if (newRadius <= point_radius_) {
  620. hovered_point_.figure = PolyFigure;
  621. hovered_point_.figureID = i;
  622. hovered_point_.pointID = j;
  623. repaint_needed_ = 1;
  624. return;
  625. /* NOTREACHED */
  626. }
  627. }
  628. }
  629. for (int i = 0; i < list_bounding_box_->count(); i++) {
  630. QRect rect = list_bounding_box_->at(i)->rect;
  631. for (int j = 0; j < 4; j++) {
  632. if (!j) {
  633. xc = rect.left();
  634. yc = rect.top();
  635. }
  636. else if (1 == j)
  637. {
  638. xc = rect.right();
  639. yc = rect.top();
  640. }
  641. else if (2 == j)
  642. {
  643. xc = rect.right();
  644. yc = rect.bottom();
  645. }
  646. else if (3 == j)
  647. {
  648. xc = rect.left();
  649. yc = rect.bottom();
  650. }
  651. newRadius = qSqrt(qPow(x - xc, 2) + qPow(y - yc, 2));
  652. if (newRadius <= point_radius_) {
  653. hovered_point_.figure = RectFigure;
  654. hovered_point_.figureID = i;
  655. hovered_point_.pointID = j;
  656. repaint_needed_ = 1;
  657. return;
  658. /* NOTREACHED */
  659. }
  660. }
  661. }
  662. hovered_point_.figure = NoFigure;
  663. hovered_point_.figureID = -1;
  664. hovered_point_.pointID = -1;
  665. repaint_needed_ = 1;
  666. }
  667. //! Returns position index of the point in polygon
  668. /*!
  669. * \param[in] aPos point to insert into the polygon
  670. * \param[in] aPoly polygon
  671. */
  672. int
  673. ImageHolder::posInPolygon(QPoint *aPos, QPolygon *aPoly) const
  674. {
  675. if (!aPos || !aPoly || aPoly->count() < 2 || aPos->isNull()) {
  676. return -1;
  677. /* NOTREACHED */
  678. }
  679. int x = aPos->x();
  680. int y = aPos->y();
  681. int index = 0;
  682. int dist = 100000;
  683. int temp = 0;
  684. int count = aPoly->count();
  685. QRect rect;
  686. for (int i = 0; i < count - 1; i++) {
  687. temp = pointToLineDistance(
  688. QLine(aPoly->at(i), aPoly->at(i + 1)),
  689. *aPos
  690. );
  691. rect.setTopLeft(aPoly->at(i));
  692. rect.setBottomRight(aPoly->at(i + 1));
  693. rect = rect.normalized();
  694. if (temp < dist &&
  695. ((x < rect.right() && rect.left() < x) ||
  696. (y < rect.bottom() && rect.top() < y)))
  697. {
  698. dist = temp;
  699. index = i + 1;
  700. }
  701. }
  702. /* first and last points */
  703. temp = pointToLineDistance(
  704. QLine(aPoly->at(0), aPoly->at(count - 1)),
  705. *aPos
  706. );
  707. rect.setTopLeft(aPoly->at(0));
  708. rect.setBottomRight(aPoly->at(count - 1));
  709. rect = rect.normalized();
  710. if (temp < dist &&
  711. ((x < rect.right() && rect.left() < x) ||
  712. (y < rect.bottom() && rect.top() < y)))
  713. {
  714. index = 0;
  715. }
  716. return index;
  717. }
  718. //! Removes selected point from focused polygon
  719. void
  720. ImageHolder::removeSelectedPoint()
  721. {
  722. if (-1 == selected_point_ ||
  723. -1 == focused_selection_ ||
  724. focused_selection_type_ != PolyFigure)
  725. {
  726. return;
  727. /* NOTREACHED */
  728. }
  729. list_polygon_->at(focused_selection_)->poly.remove(selected_point_);
  730. selected_point_ = -1;
  731. update();
  732. }
  733. void
  734. ImageHolder::keyPressEvent(QKeyEvent *anEvent)
  735. {
  736. QLabel::keyPressEvent(anEvent);
  737. }
  738. //! Event is automatically called on every mouse move
  739. /*!
  740. * With the help of this event all the mouse movements are being tracked.
  741. */
  742. void
  743. ImageHolder::mouseMoveEvent(QMouseEvent *anEvent)
  744. {
  745. QPoint pos = anEvent->pos() / scale_;
  746. if (anEvent->pos().x() < 0)
  747. pos.setX(0);
  748. if (width() < anEvent->pos().x())
  749. pos.setX(width() - 1);
  750. if (anEvent->pos().y() < 0)
  751. pos.setY(0);
  752. if (height() < anEvent->pos().y())
  753. pos.setY(height() - 1);
  754. /* modifying rectangle */
  755. if ((anEvent->buttons() & Qt::LeftButton) &&
  756. BoundingBoxTool == tool_ &&
  757. NewSelection == state_ &&
  758. Qt::NoModifier == keyboard_modifier_)
  759. {
  760. triggerBoundBox(pos, prev_cursor_pos_, &(bounding_box_.rect));
  761. }
  762. /* moving last point of the poly during creating a new one */
  763. if (PolygonTool == tool_ &&
  764. NewSelection == state_ &&
  765. (anEvent->buttons() & Qt::LeftButton))
  766. {
  767. polygon_.poly.setPoint(polygon_.poly.count() - 1, pos);
  768. repaint_needed_ = 1;
  769. }
  770. if (-1 != focused_selection_ &&
  771. !(anEvent->buttons() & Qt::LeftButton)) {
  772. checkForPoints(&pos);
  773. }
  774. /* editing polygons */
  775. if (-1 != hovered_point_.figureID &&
  776. !list_polygon_->isEmpty() &&
  777. PolyFigure == hovered_point_.figure &&
  778. (anEvent->buttons() & Qt::LeftButton) &&
  779. hovered_point_.figureID == focused_selection_)
  780. {
  781. Polygon *poly = list_polygon_->at(hovered_point_.figureID);
  782. poly->poly.setPoint(hovered_point_.pointID, pos);
  783. repaint_needed_ = 1;
  784. }
  785. /* editing bounding boxes */
  786. if (-1 != hovered_point_.figureID &&
  787. !list_bounding_box_->isEmpty() &&
  788. RectFigure == hovered_point_.figure &&
  789. (anEvent->buttons() & Qt::LeftButton))
  790. {
  791. BoundingBox *rect = list_bounding_box_->at(hovered_point_.figureID);
  792. if (0 == hovered_point_.pointID)
  793. rect->rect.setTopLeft(pos);
  794. else if (1 == hovered_point_.pointID)
  795. rect->rect.setTopRight(pos);
  796. else if (2 == hovered_point_.pointID)
  797. rect->rect.setBottomRight(pos);
  798. else if (3 == hovered_point_.pointID)
  799. rect->rect.setBottomLeft(pos);
  800. repaint_needed_ = 1;
  801. }
  802. if (repaint_needed_) {
  803. update();
  804. repaint_needed_ = 0;
  805. }
  806. }
  807. //! Event is automatically called on every mouse click
  808. /*!
  809. * Every time mouse was clicked it's position is stored in the prev_cursor_pos_
  810. * Depending on current state and selected tool it creates new points or
  811. * starts new rects
  812. */
  813. void
  814. ImageHolder::mousePressEvent(QMouseEvent *anEvent)
  815. {
  816. /* remembering coordinates of the click */
  817. if ((anEvent->buttons() & Qt::LeftButton) ||
  818. (anEvent->buttons() & Qt::RightButton))
  819. {
  820. prev_cursor_pos_ = anEvent->pos() / scale_;
  821. }
  822. QPoint pos = anEvent->pos() / scale_;
  823. if (anEvent->buttons() & Qt::LeftButton) {
  824. /* clearing the selected area if it is not confirmed */
  825. if (NewSelection == state_ && BoundingBoxTool == tool_) {
  826. bounding_box_.rect.setRect(-1, -1, 0, 0);
  827. state_ = StandBy;
  828. }
  829. /* making new points for poly */
  830. if (PolygonTool == tool_ &&
  831. NewSelection == state_ &&
  832. Qt::NoModifier == keyboard_modifier_)
  833. {
  834. triggerPolygon(pos, &(polygon_.poly));
  835. }
  836. /* starting new selection by click */
  837. if (StandBy == state_ && NoTool != tool_ &&
  838. -1 == focused_selection_) {
  839. state_ = NewSelection;
  840. emit selectionStarted();
  841. polygon_.poly.clear();
  842. if (PolygonTool == tool_) {
  843. polygon_.poly << prev_cursor_pos_;
  844. }
  845. }
  846. /* selecting a point */
  847. selected_point_ = -1;
  848. repaint_needed_ = 1;
  849. if (-1 != hovered_point_.figureID &&
  850. !list_polygon_->isEmpty() &&
  851. PolyFigure == hovered_point_.figure &&
  852. hovered_point_.figureID == focused_selection_)
  853. {
  854. selected_point_ = hovered_point_.pointID;
  855. }
  856. }
  857. if (repaint_needed_) {
  858. update();
  859. repaint_needed_ = 0;
  860. }
  861. }
  862. void
  863. ImageHolder::mouseDoubleClickEvent(QMouseEvent *anEvent)
  864. {
  865. QPoint pos = anEvent->pos() / scale_;
  866. /* new point for polygon */
  867. if (-1 == hovered_point_.figureID &&
  868. !list_polygon_->isEmpty() &&
  869. -1 != focused_selection_ &&
  870. PolyFigure == focused_selection_type_ &&
  871. (anEvent->buttons() & Qt::LeftButton))
  872. {
  873. Polygon *poly = list_polygon_->at(focused_selection_);
  874. int index = posInPolygon(&pos, &(poly->poly));
  875. if (index < 0 || poly->poly.count() <= index) {
  876. return;
  877. /* NOTREACHED */
  878. }
  879. poly->poly.insert(index, pos);
  880. repaint_needed_ = 1;
  881. }
  882. if (repaint_needed_) {
  883. update();
  884. repaint_needed_ = 0;
  885. }
  886. }
  887. //! Event is automatically called on every mouse release
  888. void
  889. ImageHolder::mouseReleaseEvent(QMouseEvent *anEvent)
  890. {
  891. Q_UNUSED(anEvent)
  892. if (-1 != hovered_point_.figureID)
  893. emit areaEdited();
  894. if (RectFigure == hovered_point_.figure &&
  895. -1 != hovered_point_.figureID &&
  896. !list_bounding_box_->
  897. at(hovered_point_.figureID)->
  898. rect.isValid()
  899. )
  900. {
  901. BoundingBox *rect = list_bounding_box_->at(hovered_point_.figureID);
  902. rect->rect = rect->rect.normalized();
  903. }
  904. }
  905. /*
  906. *
  907. */