• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.12
  • kdeedu
  • marble
  • src
  • lib
  • marble
ClipPainter.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2006-2009 Torsten Rahn <tackat@kde.org>
9 // Copyright 2007 Inge Wallin <ingwa@kde.org>
10 //
11 
12 
13 #include "ClipPainter.h"
14 
15 #include <cmath>
16 
17 #include "MarbleDebug.h"
18 
19 // #define DEBUG_DRAW_NODES
20 
21 namespace Marble
22 {
23 
24 class ClipPainterPrivate
25 {
26  public:
27  ClipPainterPrivate( ClipPainter * parent );
28 
29  ClipPainter * q;
30 
31  // true if clipping is on.
32  bool m_doClip;
33 
34  // The limits
35  qreal m_left;
36  qreal m_right;
37  qreal m_top;
38  qreal m_bottom;
39 
40  // Used in the paint process of vectors..
41  int m_currentSector;
42  int m_previousSector;
43 
44  // int m_debugNodeCount;
45 
46  QPointF m_currentPoint;
47  QPointF m_previousPoint;
48 
49  inline int sector( const QPointF & point ) const;
50 
51  inline QPointF clipTop( qreal m, const QPointF & point ) const;
52  inline QPointF clipLeft( qreal m, const QPointF & point ) const;
53  inline QPointF clipBottom( qreal m, const QPointF & point ) const;
54  inline QPointF clipRight( qreal m, const QPointF & point ) const;
55 
56  inline void initClipRect();
57 
58  inline void clipPolyObject ( const QPolygonF & sourcePolygon,
59  QVector<QPolygonF> & clippedPolyObjects,
60  bool isClosed );
61 
62  inline void clipMultiple( QPolygonF & clippedPolyObject,
63  QVector<QPolygonF> & clippedPolyObjects,
64  bool isClosed );
65  inline void clipOnce( QPolygonF & clippedPolyObject,
66  QVector<QPolygonF> & clippedPolyObjects,
67  bool isClosed );
68  inline void clipOnceCorner( QPolygonF & clippedPolyObject,
69  QVector<QPolygonF> & clippedPolyObjects,
70  const QPointF& corner,
71  const QPointF& point,
72  bool isClosed );
73  inline void clipOnceEdge( QPolygonF & clippedPolyObject,
74  QVector<QPolygonF> & clippedPolyObjects,
75  const QPointF& point,
76  bool isClosed );
77 
78 
79  void labelPosition( const QPolygonF & polygon, QVector<QPointF>& labelNodes,
80  LabelPositionFlags labelPositionFlags);
81 
82  bool pointAllowsLabel( const QPointF& point );
83  QPointF interpolateLabelPoint( const QPointF& previousPoint,
84  const QPointF& currentPoint,
85  LabelPositionFlags labelPositionFlags );
86 
87  inline qreal _m( const QPointF & start, const QPointF & end ) const;
88 
89 #ifdef DEBUG_DRAW_NODES
90  void debugDrawNodes( const QPolygonF & );
91 #endif
92 
93  qreal m_labelAreaMargin;
94 };
95 
96 }
97 
98 using namespace Marble;
99 
100 // #define MARBLE_DEBUG
101 
102 ClipPainter::ClipPainter(QPaintDevice * pd, bool clip)
103  : QPainter( pd ), d( new ClipPainterPrivate( this ) )
104 {
105  d->initClipRect();
106 
107  // m_debugNodeCount = 0;
108  d->m_doClip = clip;
109 }
110 
111 
112 ClipPainter::ClipPainter()
113  : d( new ClipPainterPrivate( this ) )
114 {
115 }
116 
117 
118 ClipPainter::~ClipPainter()
119 {
120  delete d;
121 }
122 
123 
124 void ClipPainter::setClipping(bool enable)
125 {
126  d->m_doClip = enable;
127 }
128 
129 
130 bool ClipPainter::isClipping() const
131 {
132  return d->m_doClip;
133 }
134 
135 
136 void ClipPainter::drawPolygon ( const QPolygonF & polygon,
137  Qt::FillRule fillRule )
138 {
139  d->initClipRect();
140 
141  if ( d->m_doClip ) {
142  QVector<QPolygonF> clippedPolyObjects;
143 
144  d->clipPolyObject( polygon, clippedPolyObjects, true );
145 
146  foreach( const QPolygonF & clippedPolyObject, clippedPolyObjects ) {
147  if ( clippedPolyObject.size() > 2 ) {
148  // mDebug() << "Size: " << clippedPolyObject.size();
149  QPainter::drawPolygon ( clippedPolyObject, fillRule );
150  // mDebug() << "done";
151  #ifdef DEBUG_DRAW_NODES
152  d->debugDrawNodes( clippedPolyObject );
153  #endif
154  }
155  }
156  }
157  else {
158  QPainter::drawPolygon ( polygon, fillRule );
159 
160  #ifdef DEBUG_DRAW_NODES
161  d->debugDrawNodes( polygon );
162  #endif
163  }
164 }
165 
166 void ClipPainter::drawPolyline( const QPolygonF & polygon )
167 {
168  d->initClipRect();
169 
170  if ( d->m_doClip ) {
171  QVector<QPolygonF> clippedPolyObjects;
172 
173  d->clipPolyObject( polygon, clippedPolyObjects, false );
174 
175  foreach( const QPolygonF & clippedPolyObject, clippedPolyObjects ) {
176  if ( clippedPolyObject.size() > 1 ) {
177  // mDebug() << "Size: " << clippedPolyObject.size();
178  QPainter::drawPolyline ( clippedPolyObject );
179  // mDebug() << "done";
180 
181  #ifdef DEBUG_DRAW_NODES
182  d->debugDrawNodes( clippedPolyObject );
183  #endif
184  }
185  }
186  }
187  else {
188  QPainter::drawPolyline( polygon );
189 
190  #ifdef DEBUG_DRAW_NODES
191  d->debugDrawNodes( polygon );
192  #endif
193  }
194 }
195 
196 void ClipPainter::drawPolyline( const QPolygonF & polygon, QVector<QPointF>& labelNodes,
197  LabelPositionFlags positionFlags)
198 {
199  d->initClipRect();
200 
201  if ( d->m_doClip ) {
202 
203  QVector<QPolygonF> clippedPolyObjects;
204 
205  d->clipPolyObject( polygon, clippedPolyObjects, false );
206 
207  foreach( const QPolygonF & clippedPolyObject, clippedPolyObjects ) {
208  if ( clippedPolyObject.size() > 1 ) {
209  // mDebug() << "Size: " << clippedPolyObject.size();
210  QPainter::drawPolyline ( clippedPolyObject );
211  // mDebug() << "done";
212 
213  #ifdef DEBUG_DRAW_NODES
214  d->debugDrawNodes( clippedPolyObject );
215  #endif
216 
217  d->labelPosition( clippedPolyObject, labelNodes, positionFlags );
218  }
219  }
220  }
221  else {
222  QPainter::drawPolyline( polygon );
223 
224  #ifdef DEBUG_DRAW_NODES
225  d->debugDrawNodes( polygon );
226  #endif
227 
228  d->labelPosition( polygon, labelNodes, positionFlags );
229  }
230 }
231 
232 void ClipPainterPrivate::labelPosition( const QPolygonF & polygon, QVector<QPointF>& labelNodes,
233  LabelPositionFlags labelPositionFlags)
234 {
235  int labelPosition = 0;
236 
237  bool currentAllowsLabel = false;
238 
239  if ( labelPositionFlags.testFlag( LineCenter ) ) {
240  // The Label at the center of the polyline:
241  labelPosition = static_cast<int>( polygon.size() / 2.0 );
242  if ( polygon.size() > 0 ) {
243  if ( labelPosition >= polygon.size() ) {
244  labelPosition = polygon.size() - 1;
245  }
246  labelNodes << polygon.at( labelPosition );
247  }
248  }
249 
250  if ( polygon.size() > 0 && labelPositionFlags.testFlag( LineStart ) ) {
251  if ( pointAllowsLabel( polygon.first() ) ) {
252  labelNodes << polygon.first();
253  }
254 
255  // The Label at the start of the polyline:
256  for ( int it = 1; it < polygon.size(); ++it ) {
257  currentAllowsLabel = pointAllowsLabel( polygon.at( it ) );
258 
259  if ( currentAllowsLabel ) {
260  // As polygon.size() > 0 it's ensured that it-1 exists.
261  QPointF node = interpolateLabelPoint( polygon.at( it -1 ), polygon.at( it ),
262  labelPositionFlags );
263  if ( node != QPointF( -1.0, -1.0 ) ) {
264  labelNodes << node;
265  }
266  break;
267  }
268  }
269  }
270 
271  if ( polygon.size() > 1 && labelPositionFlags.testFlag( LineEnd ) ) {
272  if ( pointAllowsLabel( polygon.at( polygon.size() - 1 ) ) ) {
273  labelNodes << polygon.at( polygon.size() - 1 );
274  }
275 
276  // The Label at the end of the polyline:
277  for ( int it = polygon.size() - 2; it > 0; --it ) {
278  currentAllowsLabel = pointAllowsLabel( polygon.at( it ) );
279 
280  if ( currentAllowsLabel ) {
281  QPointF node = interpolateLabelPoint( polygon.at( it + 1 ), polygon.at( it ),
282  labelPositionFlags );
283  if ( node != QPointF( -1.0, -1.0 ) ) {
284  labelNodes << node;
285  }
286  break;
287  }
288  }
289  }
290 }
291 
292 bool ClipPainterPrivate::pointAllowsLabel( const QPointF& point )
293 {
294 
295  if ( point.x() > m_labelAreaMargin && point.x() < q->viewport().width() - m_labelAreaMargin
296  && point.y() > m_labelAreaMargin && point.y() < q->viewport().height() - m_labelAreaMargin ) {
297  return true;
298  }
299  return false;
300 }
301 
302 QPointF ClipPainterPrivate::interpolateLabelPoint( const QPointF& previousPoint,
303  const QPointF& currentPoint,
304  LabelPositionFlags labelPositionFlags )
305 {
306  qreal m = _m( previousPoint, currentPoint );
307  if ( previousPoint.x() <= m_labelAreaMargin ) {
308  if ( labelPositionFlags.testFlag( IgnoreXMargin ) ) {
309  return QPointF( -1.0, -1.0 );
310  }
311  return QPointF( m_labelAreaMargin,
312  previousPoint.y() + ( m_labelAreaMargin - previousPoint.x() ) * m );
313  }
314  else if ( previousPoint.x() >= q->viewport().width() - m_labelAreaMargin ) {
315  if ( labelPositionFlags.testFlag( IgnoreXMargin ) ) {
316  return QPointF( -1.0, -1.0 );
317  }
318  return QPointF( q->viewport().width() - m_labelAreaMargin,
319  previousPoint.y() -
320  ( previousPoint.x() - q->viewport().width() + m_labelAreaMargin ) * m );
321  }
322 
323  if ( previousPoint.y() <= m_labelAreaMargin ) {
324  if ( labelPositionFlags.testFlag( IgnoreYMargin ) ) {
325  return QPointF( -1.0, -1.0 );
326  }
327  return QPointF( previousPoint.x() + ( m_labelAreaMargin - previousPoint.y() ) / m,
328  m_labelAreaMargin );
329  }
330  else if ( previousPoint.y() >= q->viewport().height() - m_labelAreaMargin ) {
331  if ( labelPositionFlags.testFlag( IgnoreYMargin ) ) {
332  return QPointF( -1.0, -1.0 );
333  }
334  return QPointF( previousPoint.x() -
335  ( previousPoint.y() - q->viewport().height() + m_labelAreaMargin ) / m,
336  q->viewport().height() - m_labelAreaMargin );
337  }
338 
339 // mDebug() << Q_FUNC_INFO << "Previous and current node position are allowed!";
340 
341  return QPointF( -1.0, -1.0 );
342 }
343 
344 ClipPainterPrivate::ClipPainterPrivate( ClipPainter * parent )
345  : m_doClip( true ),
346  m_left(0.0),
347  m_right(0.0),
348  m_top(0.0),
349  m_bottom(0.0),
350  m_currentSector(4),
351  m_previousSector(4),
352  m_currentPoint(QPointF()),
353  m_previousPoint(QPointF()),
354  m_labelAreaMargin(10.0)
355 {
356  q = parent;
357 }
358 
359 void ClipPainterPrivate::initClipRect ()
360 {
361  qreal penHalfWidth = q->pen().widthF() / 2.0 + 1.0;
362 
363  m_left = -penHalfWidth;
364  m_right = (qreal)(q->device()->width()) + penHalfWidth;
365  m_top = -penHalfWidth;
366  m_bottom = (qreal)(q->device()->height()) + penHalfWidth;
367 }
368 
369 qreal ClipPainterPrivate::_m( const QPointF & start, const QPointF & end ) const
370 {
371  qreal divisor = end.x() - start.x();
372  if ( std::fabs( divisor ) < 0.000001 ) {
373  // this is in screencoordinates so the difference
374  // between 0, 0.000001 and -0.000001 isn't visible at all
375  divisor = 0.000001;
376  }
377 
378  return ( end.y() - start.y() )
379  / divisor;
380 }
381 
382 
383 QPointF ClipPainterPrivate::clipTop( qreal m, const QPointF & point ) const
384 {
385  return QPointF( ( m_top - point.y() ) / m + point.x(), m_top );
386 }
387 
388 QPointF ClipPainterPrivate::clipLeft( qreal m, const QPointF & point ) const
389 {
390  return QPointF( m_left, ( m_left - point.x() ) * m + point.y() );
391 }
392 
393 QPointF ClipPainterPrivate::clipBottom( qreal m, const QPointF & point ) const
394 {
395  return QPointF( ( m_bottom - point.y() ) / m + point.x(), m_bottom );
396 }
397 
398 QPointF ClipPainterPrivate::clipRight( qreal m, const QPointF & point ) const
399 {
400  return QPointF( m_right, ( m_right - point.x() ) * m + point.y() );
401 }
402 
403 int ClipPainterPrivate::sector( const QPointF & point ) const
404 {
405  // If we think of the image borders as (infinitely long) parallel
406  // lines then the plane is divided into 9 sectors. Each of these
407  // sections is identified by a unique keynumber (currentSector):
408  //
409  // 0 | 1 | 2
410  // --+---+--
411  // 3 | 4 | 5 <- sector number "4" represents the onscreen sector / viewport
412  // --+---+--
413  // 6 | 7 | 8
414  //
415 
416  // Figure out the section of the current point.
417  int xSector = 1;
418  if ( point.x() < m_left )
419  xSector = 0;
420  else if ( point.x() > m_right )
421  xSector = 2;
422 
423  int ySector = 3;
424  if ( point.y() < m_top )
425  ySector = 0;
426  else if ( point.y() > m_bottom )
427  ySector = 6;
428 
429  // By adding xSector and ySector we get a
430  // sector number of the values shown in the ASCII-art graph above.
431  return ySector + xSector;
432 
433 }
434 
435 void ClipPainterPrivate::clipPolyObject ( const QPolygonF & polygon,
436  QVector<QPolygonF> & clippedPolyObjects,
437  bool isClosed )
438 {
439  // mDebug() << "ClipPainter enabled." ;
440 
441  // Only create a new polyObject as soon as we know for sure that
442  // the current point is on the screen.
443  QPolygonF clippedPolyObject = QPolygonF();
444 
445  const QVector<QPointF>::const_iterator itStartPoint = polygon.constBegin();
446  const QVector<QPointF>::const_iterator itEndPoint = polygon.constEnd();
447  QVector<QPointF>::const_iterator itPoint = itStartPoint;
448 
449  // We use a while loop to be able to cover linestrings as well as linear rings:
450  // Linear rings require to tessellate the path from the last node to the first node
451  // which isn't really convenient to achieve with a for loop ...
452 
453  bool processingLastNode = false;
454 
455  while ( itPoint != itEndPoint ) {
456  m_currentPoint = (*itPoint);
457  // mDebug() << "m_currentPoint.x()" << m_currentPoint.x() << "m_currentPOint.y()" << m_currentPoint.y();
458 
459  // Figure out the sector of the current point.
460  m_currentSector = sector( m_currentPoint );
461 
462  // Initialize the variables related to the previous point.
463  if ( itPoint == itStartPoint && processingLastNode == false ) {
464  if ( isClosed ) {
465  m_previousPoint = polygon.last();
466 
467  // Figure out the sector of the previous point.
468  m_previousSector = sector( m_previousPoint );
469  }
470  else {
471  m_previousSector = m_currentSector;
472  }
473  }
474 
475  // If the current point reaches a new sector, take care of clipping.
476  if ( m_currentSector != m_previousSector ) {
477  if ( m_currentSector == 4 || m_previousSector == 4 ) {
478  // In this case the current or the previous point is visible on the
479  // screen but not both. Hence we only need to clip once and require
480  // only one interpolation for both cases.
481 
482  clipOnce( clippedPolyObject, clippedPolyObjects, isClosed );
483  }
484  else {
485  // This case mostly deals with lines that reach from one
486  // sector that is located off screen to another one that
487  // is located off screen. In this situation the line
488  // can get clipped once, twice, or not at all.
489  clipMultiple( clippedPolyObject, clippedPolyObjects, isClosed );
490  }
491 
492  m_previousSector = m_currentSector;
493  }
494 
495  // If the current point is onscreen, just add it to our final polygon.
496  if ( m_currentSector == 4 ) {
497 
498  clippedPolyObject << m_currentPoint;
499 #ifdef MARBLE_DEBUG
500  ++(m_debugNodeCount);
501 #endif
502  }
503 
504  m_previousPoint = m_currentPoint;
505 
506  // Now let's handle the case where we have a (closed) polygon and where the
507  // last point of the polyline is outside the viewport and the start point
508  // is inside the viewport. This needs special treatment
509  if ( processingLastNode ) {
510  break;
511  }
512  ++itPoint;
513 
514  if ( itPoint == itEndPoint && isClosed ) {
515  itPoint = itStartPoint;
516  processingLastNode = true;
517  }
518  }
519 
520  // Only add the pointer if there's node data available.
521  if ( !clippedPolyObject.isEmpty() ) {
522  clippedPolyObjects << clippedPolyObject;
523  }
524 }
525 
526 
527 void ClipPainterPrivate::clipMultiple( QPolygonF & clippedPolyObject,
528  QVector<QPolygonF> & clippedPolyObjects,
529  bool isClosed )
530 {
531  Q_UNUSED( clippedPolyObjects )
532  Q_UNUSED( isClosed )
533 
534  // Take care of adding nodes in the image corners if the iterator
535  // traverses off screen sections.
536 
537  qreal m = _m( m_previousPoint, m_currentPoint );
538 
539  switch ( m_currentSector ) {
540  case 0:
541  if ( m_previousSector == 5 ) {
542  QPointF pointRight = clipRight( m, m_previousPoint );
543  QPointF pointTop = clipTop( m, m_currentPoint );
544  QPointF pointLeft = clipLeft( m, m_currentPoint );
545 
546  if ( pointRight.y() > m_top ) {
547  clippedPolyObject << pointRight;
548  } else {
549  clippedPolyObject << QPointF( m_right, m_top );
550  }
551  if ( pointTop.x() >= m_left && pointTop.x() < m_right )
552  clippedPolyObject << pointTop;
553  if ( pointLeft.y() > m_top )
554  clippedPolyObject << pointLeft;
555  }
556  else if ( m_previousSector == 7 ) {
557  QPointF pointBottom = clipBottom( m, m_previousPoint );
558  QPointF pointTop = clipTop( m, m_currentPoint );
559  QPointF pointLeft = clipLeft( m, m_currentPoint );
560 
561  if ( pointBottom.x() > m_left ) {
562  clippedPolyObject << pointBottom;
563  } else {
564  clippedPolyObject << QPointF( m_left, m_bottom );
565  }
566  if ( pointLeft.y() >= m_top && pointLeft.y() < m_bottom )
567  clippedPolyObject << pointLeft;
568  if ( pointTop.x() > m_left )
569  clippedPolyObject << pointTop;
570  }
571  else if ( m_previousSector == 8 ) {
572  QPointF pointBottom = clipBottom( m, m_previousPoint );
573  QPointF pointRight = clipRight( m, m_previousPoint );
574  QPointF pointTop = clipTop( m, m_currentPoint );
575  QPointF pointLeft = clipLeft( m, m_currentPoint );
576 
577  if ( pointBottom.x() > m_left && pointBottom.x() < m_right )
578  clippedPolyObject << pointBottom;
579  if ( pointRight.y() > m_top && pointRight.y() < m_bottom )
580  clippedPolyObject << pointRight;
581  if ( pointTop.x() > m_left && pointTop.x() < m_right )
582  clippedPolyObject << pointTop;
583  if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom )
584  clippedPolyObject << pointLeft;
585 
586  if ( pointBottom.x() <= m_left && pointLeft.y() >= m_bottom )
587  clippedPolyObject << QPointF( m_left, m_bottom );
588  if ( pointTop.x() >= m_right && pointRight.y() <= m_top )
589  clippedPolyObject << QPointF( m_right, m_top );
590  }
591 
592  clippedPolyObject << QPointF( m_left, m_top );
593  break;
594 
595  case 1:
596  if ( m_previousSector == 3 ) {
597  QPointF pointLeft = clipLeft( m, m_previousPoint );
598  QPointF pointTop = clipTop( m, m_currentPoint );
599 
600  if ( pointLeft.y() > m_top ) {
601  clippedPolyObject << pointLeft;
602  } else {
603  clippedPolyObject << QPointF( m_left, m_top );
604  }
605  if ( pointTop.x() > m_left )
606  clippedPolyObject << pointTop;
607  }
608  else if ( m_previousSector == 5 ) {
609  QPointF pointRight = clipRight( m, m_previousPoint );
610  QPointF pointTop = clipTop( m, m_currentPoint );
611 
612  if ( pointRight.y() > m_top ) {
613  clippedPolyObject << pointRight;
614  } else {
615  clippedPolyObject << QPointF( m_right, m_top );
616  }
617  if ( pointTop.x() < m_right )
618  clippedPolyObject << pointTop;
619  }
620  else if ( m_previousSector == 6 ) {
621  QPointF pointBottom = clipBottom( m, m_previousPoint );
622  QPointF pointLeft = clipLeft( m, m_previousPoint );
623  QPointF pointTop = clipTop( m, m_currentPoint );
624 
625  if ( pointBottom.x() > m_left )
626  clippedPolyObject << pointBottom;
627  if ( pointLeft.y() > m_top && pointLeft.y() <= m_bottom )
628  clippedPolyObject << pointLeft;
629  if ( pointTop.x() > m_left ) {
630  clippedPolyObject << pointTop;
631  } else {
632  clippedPolyObject << QPointF( m_left, m_top );
633  }
634  }
635  else if ( m_previousSector == 7 ) {
636  clippedPolyObject << clipBottom( m, m_previousPoint );
637  clippedPolyObject << clipTop( m, m_currentPoint );
638  }
639  else if ( m_previousSector == 8 ) {
640  QPointF pointBottom = clipBottom( m, m_previousPoint );
641  QPointF pointRight = clipRight( m, m_previousPoint );
642  QPointF pointTop = clipTop( m, m_currentPoint );
643 
644  if ( pointBottom.x() < m_right )
645  clippedPolyObject << pointBottom;
646  if ( pointRight.y() > m_top && pointRight.y() <= m_bottom )
647  clippedPolyObject << pointRight;
648  if ( pointTop.x() < m_right ) {
649  clippedPolyObject << pointTop;
650  } else {
651  clippedPolyObject << QPointF( m_right, m_top );
652  }
653  }
654  break;
655 
656  case 2:
657  if ( m_previousSector == 3 ) {
658  QPointF pointLeft = clipLeft( m, m_previousPoint );
659  QPointF pointTop = clipTop( m, m_currentPoint );
660  QPointF pointRight = clipRight( m, m_currentPoint );
661 
662  if ( pointLeft.y() > m_top ) {
663  clippedPolyObject << pointLeft;
664  } else {
665  clippedPolyObject << QPointF( m_left, m_top );
666  }
667  if ( pointTop.x() > m_left && pointTop.x() <= m_right )
668  clippedPolyObject << pointTop;
669  if ( pointRight.y() > m_top )
670  clippedPolyObject << pointRight;
671  }
672  else if ( m_previousSector == 7 ) {
673  QPointF pointBottom = clipBottom( m, m_previousPoint );
674  QPointF pointTop = clipTop( m, m_currentPoint );
675  QPointF pointRight = clipRight( m, m_currentPoint );
676 
677  if ( pointBottom.x() < m_right ) {
678  clippedPolyObject << pointBottom;
679  } else {
680  clippedPolyObject << QPointF( m_right, m_bottom );
681  }
682  if ( pointRight.y() >= m_top && pointRight.y() < m_bottom )
683  clippedPolyObject << pointRight;
684  if ( pointTop.x() < m_right )
685  clippedPolyObject << pointTop;
686  }
687  else if ( m_previousSector == 6 ) {
688  QPointF pointBottom = clipBottom( m, m_previousPoint );
689  QPointF pointLeft = clipLeft( m, m_currentPoint );
690  QPointF pointTop = clipTop( m, m_currentPoint );
691  QPointF pointRight = clipRight( m, m_previousPoint );
692 
693  if ( pointBottom.x() > m_left && pointBottom.x() < m_right )
694  clippedPolyObject << pointBottom;
695  if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom )
696  clippedPolyObject << pointLeft;
697  if ( pointTop.x() > m_left && pointTop.x() < m_right )
698  clippedPolyObject << pointTop;
699  if ( pointRight.y() > m_top && pointRight.y() < m_bottom )
700  clippedPolyObject << pointRight;
701 
702  if ( pointBottom.x() >= m_right && pointRight.y() >= m_bottom )
703  clippedPolyObject << QPointF( m_right, m_bottom );
704  if ( pointTop.x() <= m_left && pointLeft.y() <= m_top )
705  clippedPolyObject << QPointF( m_left, m_top );
706  }
707 
708  clippedPolyObject << QPointF( m_right, m_top );
709  break;
710 
711  case 3:
712  if ( m_previousSector == 7 ) {
713  QPointF pointBottom = clipBottom( m, m_previousPoint );
714  QPointF pointLeft = clipLeft( m, m_currentPoint );
715 
716  if ( pointBottom.x() > m_left )
717  clippedPolyObject << pointBottom;
718  if ( pointLeft.y() < m_bottom ) {
719  clippedPolyObject << pointLeft;
720  } else {
721  clippedPolyObject << QPointF( m_left, m_bottom );
722  }
723  }
724  else if ( m_previousSector == 1 ) {
725  QPointF pointTop = clipTop( m, m_previousPoint );
726  QPointF pointLeft = clipLeft( m, m_currentPoint );
727 
728  if ( pointTop.x() > m_left )
729  clippedPolyObject << pointTop;
730  if ( pointLeft.y() > m_top ) {
731  clippedPolyObject << pointLeft;
732  } else {
733  clippedPolyObject << QPointF( m_left, m_top );
734  }
735  }
736  else if ( m_previousSector == 8 ) {
737  QPointF pointRight = clipRight( m, m_previousPoint );
738  QPointF pointBottom = clipBottom( m, m_previousPoint );
739  QPointF pointLeft = clipLeft( m, m_currentPoint );
740 
741  if ( pointRight.y() < m_bottom )
742  clippedPolyObject << pointRight;
743  if ( pointBottom.x() > m_left && pointBottom.x() <= m_right )
744  clippedPolyObject << pointBottom;
745  if ( pointLeft.y() < m_bottom ) {
746  clippedPolyObject << pointLeft;
747  } else {
748  clippedPolyObject << QPointF( m_left, m_bottom );
749  }
750  }
751  else if ( m_previousSector == 5 ) {
752  clippedPolyObject << clipRight( m, m_previousPoint );
753  clippedPolyObject << clipLeft( m, m_currentPoint );
754  }
755  else if ( m_previousSector == 2 ) {
756  QPointF pointRight = clipRight( m, m_previousPoint );
757  QPointF pointTop = clipTop( m, m_previousPoint );
758  QPointF pointLeft = clipLeft( m, m_currentPoint );
759 
760  if ( pointRight.y() > m_top )
761  clippedPolyObject << pointRight;
762  if ( pointTop.x() > m_left && pointTop.x() <= m_right )
763  clippedPolyObject << pointTop;
764  if ( pointLeft.y() > m_top ) {
765  clippedPolyObject << pointLeft;
766  } else {
767  clippedPolyObject << QPointF( m_left, m_top );
768  }
769  }
770  break;
771 
772  case 5:
773  if ( m_previousSector == 7 ) {
774  QPointF pointBottom = clipBottom( m, m_previousPoint );
775  QPointF pointRight = clipRight( m, m_currentPoint );
776 
777  if ( pointBottom.x() < m_right )
778  clippedPolyObject << pointBottom;
779  if ( pointRight.y() < m_bottom ) {
780  clippedPolyObject << pointRight;
781  } else {
782  clippedPolyObject << QPointF( m_right, m_bottom );
783  }
784  }
785  else if ( m_previousSector == 1 ) {
786  QPointF pointTop = clipTop( m, m_previousPoint );
787  QPointF pointRight = clipRight( m, m_currentPoint );
788 
789  if ( pointTop.x() < m_right )
790  clippedPolyObject << pointTop;
791  if ( pointRight.y() > m_top ) {
792  clippedPolyObject << pointRight;
793  } else {
794  clippedPolyObject << QPointF( m_right, m_top );
795  }
796  }
797  else if ( m_previousSector == 6 ) {
798  QPointF pointLeft = clipLeft( m, m_previousPoint );
799  QPointF pointBottom = clipBottom( m, m_previousPoint );
800  QPointF pointRight = clipRight( m, m_currentPoint );
801 
802  if ( pointLeft.y() < m_bottom )
803  clippedPolyObject << pointLeft;
804  if ( pointBottom.x() >= m_left && pointBottom.x() < m_right )
805  clippedPolyObject << pointBottom;
806  if ( pointRight.y() < m_bottom ) {
807  clippedPolyObject << pointRight;
808  } else {
809  clippedPolyObject << QPointF( m_right, m_bottom );
810  }
811  }
812  else if ( m_previousSector == 3 ) {
813  clippedPolyObject << clipLeft( m, m_previousPoint );
814  clippedPolyObject << clipRight( m, m_currentPoint );
815  }
816  else if ( m_previousSector == 0 ) {
817  QPointF pointLeft = clipLeft( m, m_previousPoint );
818  QPointF pointTop = clipTop( m, m_previousPoint );
819  QPointF pointRight = clipRight( m, m_currentPoint );
820 
821  if ( pointLeft.y() > m_top )
822  clippedPolyObject << pointLeft;
823  if ( pointTop.x() >= m_left && pointTop.x() < m_right )
824  clippedPolyObject << pointTop;
825  if ( pointRight.y() > m_top ) {
826  clippedPolyObject << pointRight;
827  } else {
828  clippedPolyObject << QPointF( m_right, m_top );
829  }
830  }
831  break;
832 
833  case 6:
834  if ( m_previousSector == 5 ) {
835  QPointF pointRight = clipRight( m, m_previousPoint );
836  QPointF pointBottom = clipBottom( m, m_currentPoint );
837  QPointF pointLeft = clipLeft( m, m_currentPoint );
838 
839  if ( pointRight.y() < m_bottom ) {
840  clippedPolyObject << pointRight;
841  } else {
842  clippedPolyObject << QPointF( m_right, m_bottom );
843  }
844  if ( pointBottom.x() >= m_left && pointBottom.x() < m_right )
845  clippedPolyObject << pointBottom;
846  if ( pointLeft.y() < m_bottom )
847  clippedPolyObject << pointLeft;
848  }
849  else if ( m_previousSector == 1 ) {
850  QPointF pointTop = clipTop( m, m_previousPoint );
851  QPointF pointLeft = clipLeft( m, m_currentPoint );
852  QPointF pointBottom = clipBottom( m, m_currentPoint );
853 
854  if ( pointTop.x() > m_left ) {
855  clippedPolyObject << pointTop;
856  } else {
857  clippedPolyObject << QPointF( m_left, m_top );
858  }
859  if ( pointLeft.y() > m_top && pointLeft.y() <= m_bottom )
860  clippedPolyObject << pointLeft;
861  if ( pointBottom.x() > m_left )
862  clippedPolyObject << pointBottom;
863  }
864  else if ( m_previousSector == 2 ) {
865  QPointF pointTop = clipTop( m, m_currentPoint );
866  QPointF pointRight = clipRight( m, m_previousPoint );
867  QPointF pointBottom = clipBottom( m, m_previousPoint );
868  QPointF pointLeft = clipLeft( m, m_currentPoint );
869 
870  if ( pointTop.x() > m_left && pointTop.x() < m_right )
871  clippedPolyObject << pointTop;
872  if ( pointRight.y() > m_top && pointRight.y() < m_bottom )
873  clippedPolyObject << pointRight;
874  if ( pointBottom.x() > m_left && pointBottom.x() < m_right )
875  clippedPolyObject << pointBottom;
876  if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom )
877  clippedPolyObject << pointLeft;
878 
879  if ( pointBottom.x() >= m_right && pointRight.y() >= m_bottom )
880  clippedPolyObject << QPointF( m_right, m_bottom );
881  if ( pointTop.x() <= m_left && pointLeft.y() <= m_top )
882  clippedPolyObject << QPointF( m_left, m_top );
883  }
884 
885  clippedPolyObject << QPointF( m_left, m_bottom );
886  break;
887 
888  case 7:
889  if ( m_previousSector == 3 ) {
890  QPointF pointLeft = clipLeft( m, m_previousPoint );
891  QPointF pointBottom = clipBottom( m, m_currentPoint );
892 
893  if ( pointLeft.y() < m_bottom ) {
894  clippedPolyObject << pointLeft;
895  } else {
896  clippedPolyObject << QPointF( m_left, m_bottom );
897  }
898  if ( pointBottom.x() > m_left )
899  clippedPolyObject << pointBottom;
900  }
901  else if ( m_previousSector == 5 ) {
902  QPointF pointRight = clipRight( m, m_previousPoint );
903  QPointF pointBottom = clipBottom( m, m_currentPoint );
904 
905  if ( pointRight.y() < m_bottom ) {
906  clippedPolyObject << pointRight;
907  } else {
908  clippedPolyObject << QPointF( m_right, m_bottom );
909  }
910  if ( pointBottom.x() < m_right )
911  clippedPolyObject << pointBottom;
912  }
913  else if ( m_previousSector == 0 ) {
914  QPointF pointTop = clipTop( m, m_previousPoint );
915  QPointF pointLeft = clipLeft( m, m_previousPoint );
916  QPointF pointBottom = clipBottom( m, m_currentPoint );
917 
918  if ( pointTop.x() > m_left )
919  clippedPolyObject << pointTop;
920  if ( pointLeft.y() >= m_top && pointLeft.y() < m_bottom )
921  clippedPolyObject << pointLeft;
922  if ( pointBottom.x() > m_left ) {
923  clippedPolyObject << pointBottom;
924  } else {
925  clippedPolyObject << QPointF( m_left, m_bottom );
926  }
927  }
928  else if ( m_previousSector == 1 ) {
929  clippedPolyObject << clipTop( m, m_previousPoint );
930  clippedPolyObject << clipBottom( m, m_currentPoint );
931  }
932  else if ( m_previousSector == 2 ) {
933  QPointF pointTop = clipTop( m, m_previousPoint );
934  QPointF pointRight = clipRight( m, m_previousPoint );
935  QPointF pointBottom = clipBottom( m, m_currentPoint );
936 
937  if ( pointTop.x() < m_right )
938  clippedPolyObject << pointTop;
939  if ( pointRight.y() >= m_top && pointRight.y() < m_bottom )
940  clippedPolyObject << pointRight;
941  if ( pointBottom.x() < m_right ) {
942  clippedPolyObject << pointBottom;
943  } else {
944  clippedPolyObject << QPointF( m_right, m_bottom );
945  }
946  }
947  break;
948 
949  case 8:
950  if ( m_previousSector == 3 ) {
951  QPointF pointLeft = clipLeft( m, m_previousPoint );
952  QPointF pointBottom = clipBottom( m, m_currentPoint );
953  QPointF pointRight = clipRight( m, m_currentPoint );
954 
955  if ( pointLeft.y() < m_bottom ) {
956  clippedPolyObject << pointLeft;
957  } else {
958  clippedPolyObject << QPointF( m_left, m_bottom );
959  }
960  if ( pointBottom.x() > m_left && pointBottom.x() <= m_right )
961  clippedPolyObject << pointBottom;
962  if ( pointRight.y() < m_bottom )
963  clippedPolyObject << pointRight;
964  }
965  else if ( m_previousSector == 1 ) {
966  QPointF pointTop = clipTop( m, m_previousPoint );
967  QPointF pointRight = clipRight( m, m_currentPoint );
968  QPointF pointBottom = clipBottom( m, m_currentPoint );
969 
970  if ( pointTop.x() < m_right ) {
971  clippedPolyObject << pointTop;
972  } else {
973  clippedPolyObject << QPointF( m_right, m_top );
974  }
975  if ( pointRight.y() > m_top && pointRight.y() <= m_bottom )
976  clippedPolyObject << pointRight;
977  if ( pointBottom.x() < m_right )
978  clippedPolyObject << pointBottom;
979  }
980  else if ( m_previousSector == 0 ) {
981  QPointF pointTop = clipTop( m, m_currentPoint );
982  QPointF pointLeft = clipLeft( m, m_currentPoint );
983  QPointF pointBottom = clipBottom( m, m_previousPoint );
984  QPointF pointRight = clipRight( m, m_previousPoint );
985 
986  if ( pointTop.x() > m_left && pointTop.x() < m_right )
987  clippedPolyObject << pointTop;
988  if ( pointLeft.y() > m_top && pointLeft.y() < m_bottom )
989  clippedPolyObject << pointLeft;
990  if ( pointBottom.x() > m_left && pointBottom.x() < m_right )
991  clippedPolyObject << pointBottom;
992  if ( pointRight.y() > m_top && pointRight.y() < m_bottom )
993  clippedPolyObject << pointRight;
994 
995  if ( pointBottom.x() <= m_left && pointLeft.y() >= m_bottom )
996  clippedPolyObject << QPointF( m_left, m_bottom );
997  if ( pointTop.x() >= m_right && pointRight.y() <= m_top )
998  clippedPolyObject << QPointF( m_right, m_top );
999  }
1000 
1001  clippedPolyObject << QPointF( m_right, m_bottom );
1002  break;
1003 
1004  default:
1005  break;
1006  }
1007 }
1008 
1009 void ClipPainterPrivate::clipOnceCorner( QPolygonF & clippedPolyObject,
1010  QVector<QPolygonF> & clippedPolyObjects,
1011  const QPointF& corner,
1012  const QPointF& point,
1013  bool isClosed )
1014 {
1015  Q_UNUSED( clippedPolyObjects )
1016  Q_UNUSED( isClosed )
1017 
1018  if ( m_currentSector == 4) {
1019  // Appearing
1020  clippedPolyObject << corner;
1021  clippedPolyObject << point;
1022  } else {
1023  // Disappearing
1024  clippedPolyObject << point;
1025  clippedPolyObject << corner;
1026  }
1027 }
1028 
1029 void ClipPainterPrivate::clipOnceEdge( QPolygonF & clippedPolyObject,
1030  QVector<QPolygonF> & clippedPolyObjects,
1031  const QPointF& point,
1032  bool isClosed )
1033 {
1034  if ( m_currentSector == 4) {
1035  // Appearing
1036  if ( !isClosed ) {
1037  clippedPolyObject = QPolygonF();
1038  }
1039  clippedPolyObject << point;
1040  }
1041  else {
1042  // Disappearing
1043  clippedPolyObject << point;
1044  if ( !isClosed ) {
1045  clippedPolyObjects << clippedPolyObject;
1046  }
1047  }
1048 }
1049 
1050 void ClipPainterPrivate::clipOnce( QPolygonF & clippedPolyObject,
1051  QVector<QPolygonF> & clippedPolyObjects,
1052  bool isClosed )
1053 {
1054  // Interpolate border points (linear interpolation)
1055  QPointF point;
1056 
1057  // Calculating the slope.
1058  qreal m = _m( m_previousPoint, m_currentPoint );
1059 
1060  // Calculate in which sector the end of the line is located that is off screen
1061  int offscreenpos = ( m_currentSector == 4 ) ? m_previousSector : m_currentSector;
1062 
1063  // "Rise over run" for all possible situations .
1064  switch ( offscreenpos ) {
1065  case 0: // topleft
1066  point = clipTop( m, m_previousPoint );
1067  if ( point.x() < m_left ) {
1068  point = clipLeft( m, point );
1069  }
1070  clipOnceCorner( clippedPolyObject, clippedPolyObjects, QPointF( m_left, m_top ), point, isClosed );
1071  break;
1072  case 1: // top
1073  point = clipTop( m, m_previousPoint );
1074  clipOnceEdge( clippedPolyObject, clippedPolyObjects, point, isClosed );
1075  break;
1076  case 2: // topright
1077  point = clipTop( m, m_previousPoint );
1078  if ( point.x() > m_right ) {
1079  point = clipRight( m, point );
1080  }
1081  clipOnceCorner( clippedPolyObject, clippedPolyObjects, QPointF( m_right, m_top ), point, isClosed );
1082  break;
1083  case 3: // left
1084  point = clipLeft( m, m_previousPoint );
1085  clipOnceEdge( clippedPolyObject, clippedPolyObjects, point, isClosed );
1086  break;
1087  case 5: // right
1088  point = clipRight( m, m_previousPoint );
1089  clipOnceEdge( clippedPolyObject, clippedPolyObjects, point, isClosed );
1090  break;
1091  case 6: // bottomleft
1092  point = clipBottom( m, m_previousPoint );
1093  if ( point.x() < m_left ) {
1094  point = clipLeft( m, point );
1095  }
1096  clipOnceCorner( clippedPolyObject, clippedPolyObjects, QPointF( m_left, m_bottom ), point, isClosed );
1097  break;
1098  case 7: // bottom
1099  point = clipBottom( m, m_previousPoint );
1100  clipOnceEdge( clippedPolyObject, clippedPolyObjects, point, isClosed );
1101  break;
1102  case 8: // bottomright
1103  point = clipBottom( m, m_previousPoint );
1104  if ( point.x() > m_right ) {
1105  point = clipRight( m, point );
1106  }
1107  clipOnceCorner( clippedPolyObject, clippedPolyObjects, QPointF( m_right, m_bottom ), point, isClosed );
1108  break;
1109  default:
1110  break;
1111  }
1112 
1113 }
1114 
1115 #ifdef DEBUG_DRAW_NODES
1116 
1117 void ClipPainterPrivate::debugDrawNodes( const QPolygonF & polygon )
1118 {
1119 
1120  q->save();
1121  q->setRenderHint( QPainter::Antialiasing, false );
1122 
1123  q->setPen( Qt::red );
1124  q->setBrush( Qt::transparent );
1125 
1126  const QVector<QPointF>::const_iterator itStartPoint = polygon.constBegin();
1127  const QVector<QPointF>::const_iterator itEndPoint = polygon.constEnd();
1128  QVector<QPointF>::const_iterator itPoint = itStartPoint;
1129 
1130  for (; itPoint != itEndPoint; ++itPoint ) {
1131 
1132  if ( itPoint == itStartPoint || itPoint == itStartPoint + 1 || itPoint == itStartPoint + 2 ) {
1133  q->setPen( Qt::darkGreen );
1134  if ( itPoint == itStartPoint ) {
1135  q->drawRect( itPoint->x() - 3.0, itPoint->y() - 3.0 , 6.0, 6.0 );
1136  }
1137  else if ( itPoint == itStartPoint + 1 ) {
1138  q->drawRect( itPoint->x() - 2.0, itPoint->y() - 2.0 , 4.0, 4.0 );
1139  }
1140  else {
1141  q->drawRect( itPoint->x() - 1.0, itPoint->y() - 1.0 , 2.0, 2.0 );
1142  }
1143  q->setPen( Qt::red );
1144  }
1145  else if ( itPoint == itEndPoint - 1 || itPoint == itEndPoint - 2 || itPoint == itEndPoint - 3 ) {
1146  q->setPen( Qt::blue );
1147  if ( itPoint == itEndPoint - 3 ) {
1148  q->drawRect( itPoint->x() - 3.0, itPoint->y() - 3.0 , 6.0, 6.0 );
1149  }
1150  else if ( itPoint == itEndPoint - 2 ) {
1151  q->drawRect( itPoint->x() - 2.0, itPoint->y() - 2.0 , 4.0, 4.0 );
1152  }
1153  else {
1154  q->drawRect( itPoint->x() - 1.0, itPoint->y() - 1.0 , 2.0, 2.0 );
1155  }
1156  q->setPen( Qt::red );
1157  }
1158  else {
1159  q->drawRect( itPoint->x() - 1.5, itPoint->y() - 1.5 , 3.0, 3.0 );
1160  }
1161 
1162  }
1163  q->restore();
1164 }
1165 
1166 #endif
QPainter
Marble::IgnoreYMargin
Definition: MarbleGlobal.h:114
Marble::ClipPainter::~ClipPainter
~ClipPainter()
Definition: ClipPainter.cpp:118
Marble::ClipPainter::isClipping
bool isClipping() const
Definition: ClipPainter.cpp:130
Marble::IgnoreXMargin
Definition: MarbleGlobal.h:113
MarbleDebug.h
Marble::ClipPainter::drawPolygon
void drawPolygon(const QPolygonF &, Qt::FillRule fillRule=Qt::OddEvenFill)
Definition: ClipPainter.cpp:136
Marble::ClipPainter::ClipPainter
ClipPainter()
Definition: ClipPainter.cpp:112
Marble::LineEnd
Definition: MarbleGlobal.h:112
Marble::LineCenter
Definition: MarbleGlobal.h:111
Marble::ClipPainter
Definition: ClipPainter.h:51
Marble::LineStart
Definition: MarbleGlobal.h:110
ClipPainter.h
Marble::ClipPainter::drawPolyline
void drawPolyline(const QPolygonF &)
Definition: ClipPainter.cpp:166
Marble::ClipPainter::setClipping
void setClipping(bool enable)
Definition: ClipPainter.cpp:124
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:38:49 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal