ctkTransferFunctionControlPointsItem.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*=========================================================================
  2. Library: CTK
  3. Copyright (c) Kitware Inc.
  4. Licensed under the Apache License, Version 2.0 (the "License");
  5. you may not use this file except in compliance with the License.
  6. You may obtain a copy of the License at
  7. http://www.apache.org/licenses/LICENSE-2.0.txt
  8. Unless required by applicable law or agreed to in writing, software
  9. distributed under the License is distributed on an "AS IS" BASIS,
  10. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. See the License for the specific language governing permissions and
  12. limitations under the License.
  13. =========================================================================*/
  14. /// Qt includes
  15. #include <QColor>
  16. #include <QDebug>
  17. #include <QLinearGradient>
  18. #include <QGraphicsSceneMouseEvent>
  19. #include <QPainter>
  20. #include <QtGlobal>
  21. #include <QVariant>
  22. #include <QKeyEvent>
  23. /// CTK includes
  24. #include "ctkTransferFunctionControlPointsItem.h"
  25. #include "ctkTransferFunctionRepresentation.h"
  26. #include "ctkTransferFunctionScene.h"
  27. #include "ctkTransferFunctionView.h"
  28. //-----------------------------------------------------------------------------
  29. class ctkTransferFunctionControlPointsItemPrivate
  30. {
  31. Q_DECLARE_PUBLIC(ctkTransferFunctionControlPointsItem);
  32. protected:
  33. ctkTransferFunctionControlPointsItem* q_ptr;
  34. public:
  35. ctkTransferFunctionControlPointsItemPrivate(ctkTransferFunctionControlPointsItem& object);
  36. void init();
  37. QList<QPointF> ControlPoints;
  38. QSize PointSize;
  39. int SelectedPoint;
  40. };
  41. //-----------------------------------------------------------------------------
  42. ctkTransferFunctionControlPointsItemPrivate::ctkTransferFunctionControlPointsItemPrivate(ctkTransferFunctionControlPointsItem& object)
  43. :q_ptr(&object)
  44. {
  45. this->PointSize = QSize(12,12);
  46. this->SelectedPoint = -1;
  47. }
  48. //-----------------------------------------------------------------------------
  49. void ctkTransferFunctionControlPointsItemPrivate::init()
  50. {
  51. Q_Q(ctkTransferFunctionControlPointsItem);
  52. q->setAcceptedMouseButtons(Qt::LeftButton);
  53. }
  54. //-----------------------------------------------------------------------------
  55. ctkTransferFunctionControlPointsItem::ctkTransferFunctionControlPointsItem(QGraphicsItem* parentGraphicsItem)
  56. :ctkTransferFunctionItem(parentGraphicsItem)
  57. , d_ptr(new ctkTransferFunctionControlPointsItemPrivate(*this))
  58. {
  59. Q_D(ctkTransferFunctionControlPointsItem);
  60. d->init();
  61. }
  62. //-----------------------------------------------------------------------------
  63. ctkTransferFunctionControlPointsItem::ctkTransferFunctionControlPointsItem(
  64. ctkTransferFunction* transferFunction, QGraphicsItem* parentItem)
  65. :ctkTransferFunctionItem(transferFunction, parentItem)
  66. , d_ptr(new ctkTransferFunctionControlPointsItemPrivate(*this))
  67. {
  68. Q_D(ctkTransferFunctionControlPointsItem);
  69. d->init();
  70. }
  71. //-----------------------------------------------------------------------------
  72. ctkTransferFunctionControlPointsItem::~ctkTransferFunctionControlPointsItem()
  73. {
  74. }
  75. //-----------------------------------------------------------------------------
  76. void ctkTransferFunctionControlPointsItem::paint(
  77. QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget)
  78. {
  79. Q_UNUSED(option);
  80. Q_UNUSED(widget);
  81. Q_D(ctkTransferFunctionControlPointsItem);
  82. int count = this->transferFunction() ? this->transferFunction()->count() : 0;
  83. if (count <= 0)
  84. {
  85. return;
  86. }
  87. //ctkTransferFunctionScene* tfScene = dynamic_cast<ctkTransferFunctionScene*>(this->scene());
  88. //Q_ASSERT(tfScene);
  89. ctkTransferFunctionRepresentation* tfRep = this->transferFunction()->representation();
  90. const QPainterPath& curve = tfRep->curve();
  91. QPen pen(QColor(255, 255, 255, 191), 1);
  92. pen.setCosmetic(true);
  93. painter->setPen(pen);
  94. painter->drawPath(curve);
  95. d->ControlPoints = tfRep->points();
  96. painter->setBrush(QBrush(QColor(191, 191, 191, 127)));
  97. painter->save();
  98. QTransform transform = painter->transform();
  99. painter->setTransform(QTransform());
  100. foreach(const QPointF& point, d->ControlPoints)
  101. {
  102. QPointF pos = transform.map(point);
  103. painter->drawEllipse(pos.x() - d->PointSize.width() / 2,
  104. pos.y() - d->PointSize.height() / 2,
  105. d->PointSize.width(), d->PointSize.width());
  106. //points.addEllipse(point, d->PointSize.width(), d->PointSize.height());
  107. }
  108. painter->restore();
  109. }
  110. //-----------------------------------------------------------------------------
  111. void ctkTransferFunctionControlPointsItem::mousePressEvent(QGraphicsSceneMouseEvent* e)
  112. {
  113. Q_D(ctkTransferFunctionControlPointsItem);
  114. ctkTransferFunctionView* view = qobject_cast<ctkTransferFunctionView*>(e->widget()->parentWidget());
  115. Q_ASSERT(view);
  116. // e->pos() is ok, pointArea should be in the world coordiate
  117. QRect pointViewArea(QPoint(-d->PointSize.width() / 2, -d->PointSize.height() / 2), d->PointSize);
  118. QPolygonF pointItemArea = this->mapFromScene(view->mapToScene(pointViewArea));
  119. d->SelectedPoint = -1;
  120. for(int i = 0; i < d->ControlPoints.count(); ++i)
  121. {
  122. if (pointItemArea.translated(d->ControlPoints[i]).containsPoint(e->pos(), Qt::OddEvenFill))
  123. {
  124. d->SelectedPoint = i;
  125. break;
  126. }
  127. }
  128. if (d->SelectedPoint >= 0)
  129. {
  130. return;
  131. }
  132. //ctkTransferFunctionScene* tfScene = dynamic_cast<ctkTransferFunctionScene*>(this->scene());
  133. //Q_ASSERT(tfScene);
  134. ctkTransferFunctionRepresentation* tfRep = this->transferFunction()->representation();
  135. // convert coordinates
  136. QPointF tfPos = tfRep->mapPointFromScene(e->pos());
  137. // add point to transfer function
  138. // returns index
  139. int index = this->transferFunction()->insertControlPoint( tfPos.x());
  140. //NOT WORKING IN COMPOSITE
  141. // update value of the point
  142. if (!QSharedPointer<ctkControlPoint>(this->transferFunction()->controlPoint(index))->value().canConvert<QColor>())
  143. {
  144. this->transferFunction()->setControlPointValue( index, tfPos.y());
  145. }
  146. }
  147. //-----------------------------------------------------------------------------
  148. void ctkTransferFunctionControlPointsItem::mouseMoveEvent(QGraphicsSceneMouseEvent* e)
  149. {
  150. Q_D(ctkTransferFunctionControlPointsItem);
  151. if (d->SelectedPoint < 0)
  152. {
  153. e->ignore();
  154. return;
  155. }
  156. //ctkTransferFunctionScene* tfScene = dynamic_cast<ctkTransferFunctionScene*>(this->scene());
  157. //Q_ASSERT(tfScene);
  158. ctkTransferFunctionRepresentation* tfRep = this->transferFunction()->representation();
  159. QPointF newPos = tfRep->mapPointFromScene(e->pos());
  160. // Deal with borders
  161. if(d->SelectedPoint == 0 || d->SelectedPoint == this->transferFunction()->count() )
  162. {
  163. // BEHAVIOR TO BE IMPLEMENTED
  164. // int borderBehavior = tfScene->borderBehavior();
  165. // LockBorder
  166. // Create new point on border at same height
  167. // Create new point on border on top
  168. // Create new point on border on bottom
  169. qDebug() << "border" ;
  170. return;
  171. }
  172. else
  173. {
  174. // TO BE IMPLEMENTED
  175. //int movePointsBehavior = tfScene->movePointsBehavior();
  176. // initialize to BLOCK_MOVE for now
  177. int movePointsBehavior = STOP_MOVE;
  178. switch( movePointsBehavior ){
  179. case STOP_MOVE:
  180. stopPoints(newPos);
  181. break;
  182. case SWITCH_MOVE:
  183. switchPoints(newPos);
  184. break;
  185. case DRAW_MOVE:
  186. drawPoints(newPos);
  187. break;
  188. case FUSION_MOVE:
  189. fusionPoints(newPos);
  190. break;
  191. default:
  192. break;
  193. }
  194. }
  195. }
  196. //-----------------------------------------------------------------------------
  197. void ctkTransferFunctionControlPointsItem::stopPoints( QPointF iPointF )
  198. {
  199. Q_D(ctkTransferFunctionControlPointsItem);
  200. if( this->transferFunction()->controlPoint(d->SelectedPoint - 1)->x() > iPointF.x() ||
  201. this->transferFunction()->controlPoint(d->SelectedPoint + 1)->x() < iPointF.x())
  202. {
  203. return;
  204. }
  205. updatePointPosition(iPointF);
  206. }
  207. //-----------------------------------------------------------------------------
  208. void ctkTransferFunctionControlPointsItem::switchPoints( QPointF iPointF )
  209. {
  210. Q_D(ctkTransferFunctionControlPointsItem);
  211. // Increment or decrement selected point?
  212. // Don't need to check borders since it is done just before calling this method...
  213. if( this->transferFunction()->controlPoint(d->SelectedPoint - 1)->x() > iPointF.x() )
  214. {
  215. // NOT WORKING IF COMPOSITE TRANSFER FUNCTION
  216. double value = this->transferFunction()->value(d->SelectedPoint-1 ).toDouble();
  217. d->SelectedPoint -= 1;
  218. this->transferFunction()->setControlPointValue(d->SelectedPoint+1, value);
  219. }
  220. else if ( this->transferFunction()->controlPoint(d->SelectedPoint + 1)->x() < iPointF.x() )
  221. {
  222. double value = this->transferFunction()->value(d->SelectedPoint + 1 ).toDouble();
  223. d->SelectedPoint += 1;
  224. this->transferFunction()->setControlPointValue(d->SelectedPoint-1, value);
  225. }
  226. updatePointPosition(iPointF);
  227. }
  228. //-----------------------------------------------------------------------------
  229. void ctkTransferFunctionControlPointsItem::drawPoints( QPointF iPointF )
  230. {
  231. Q_D(ctkTransferFunctionControlPointsItem);
  232. // Increment or decrement selected point
  233. if( this->transferFunction()->controlPoint(d->SelectedPoint - 1)->x() > iPointF.x() )
  234. {
  235. //change the selected point
  236. d->SelectedPoint = d->SelectedPoint -1;
  237. }
  238. else if ( this->transferFunction()->controlPoint(d->SelectedPoint + 1)->x() < iPointF.x() )
  239. {
  240. d->SelectedPoint = d->SelectedPoint +1;
  241. }
  242. updatePointPosition(iPointF);
  243. }
  244. //-----------------------------------------------------------------------------
  245. void ctkTransferFunctionControlPointsItem::fusionPoints( QPointF iPointF )
  246. {
  247. Q_UNUSED(iPointF);
  248. // TO BE IMPLEMENTED
  249. // if 2 points are to close: delete one..?
  250. }
  251. //-----------------------------------------------------------------------------
  252. void ctkTransferFunctionControlPointsItem::updatePointPosition( QPointF iPoint )
  253. {
  254. Q_D(ctkTransferFunctionControlPointsItem);
  255. this->transferFunction()->setControlPointPos(d->SelectedPoint, iPoint.x());
  256. // TEST NOT WORKING IN COMPOSITE TRANSFER FUNCTION
  257. if ( ! QSharedPointer<ctkControlPoint>(this->transferFunction()->controlPoint(d->SelectedPoint))->value().canConvert<QColor>() )
  258. {
  259. this->transferFunction()->setControlPointValue(d->SelectedPoint, iPoint.y());
  260. }
  261. }
  262. //-----------------------------------------------------------------------------
  263. void ctkTransferFunctionControlPointsItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* e)
  264. {
  265. Q_D(ctkTransferFunctionControlPointsItem);
  266. if (d->SelectedPoint < 0)
  267. {
  268. e->ignore();
  269. return;
  270. }
  271. d->SelectedPoint = -1;
  272. }
  273. //-----------------------------------------------------------------------------
  274. void ctkTransferFunctionControlPointsItem::keyPressEvent ( QKeyEvent * keyEvent )
  275. {
  276. Q_D(ctkTransferFunctionControlPointsItem);
  277. // if a point is selected, "d" and "D" = delete the point
  278. if (d->SelectedPoint >= 0)
  279. {
  280. if ( ! QString::compare(keyEvent->text(), "d") || ! QString::compare(keyEvent->text(), "D") )
  281. {
  282. // Get value of selected point
  283. qreal xValue = this->transferFunction()->controlPoint( d->SelectedPoint )->x();
  284. // remove point using value ( can't use point ID because it could engender
  285. // problems when multiple points selection implemented)
  286. this->transferFunction()->removeControlPoint( xValue );
  287. }
  288. }
  289. }