You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

177 lines
4.5 KiB

  1. #include <gal/graphics_abstraction_layer.h>
  2. #include <gal/color4d.h>
  3. #include <view/view_overlay.h>
  4. #include "label_manager.h"
  5. using KIGFX::GAL;
  6. using KIGFX::COLOR4D;
  7. using KIGFX::VIEW_OVERLAY;
  8. LABEL_MANAGER::LABEL_MANAGER( GAL* aGal ) : m_gal( aGal )
  9. {
  10. };
  11. LABEL_MANAGER::~LABEL_MANAGER()
  12. {
  13. }
  14. void LABEL_MANAGER::Add( VECTOR2I target, wxString msg, COLOR4D color )
  15. {
  16. LABEL lbl;
  17. lbl.m_target = target;
  18. lbl.m_msg = msg;
  19. lbl.m_color = color;
  20. m_gal->SetGlyphSize( VECTOR2D( m_textSize, m_textSize ) );
  21. KIFONT::FONT* strokeFont = KIFONT::FONT::GetFont( wxEmptyString );
  22. UTF8 text( msg );
  23. VECTOR2I textDims = strokeFont->StringBoundaryLimits( text, VECTOR2D( m_textSize, m_textSize ),
  24. m_textSize/8, false, false );
  25. lbl.m_bbox.SetOrigin( lbl.m_target - textDims - VECTOR2I( m_textSize, m_textSize ) );
  26. lbl.m_bbox.SetSize( textDims );
  27. m_labels.push_back( lbl );
  28. }
  29. void LABEL_MANAGER::Add( const SHAPE_LINE_CHAIN& aL, COLOR4D color )
  30. {
  31. for( int i = 0; i < aL.PointCount(); i++ )
  32. {
  33. char msg[1024];
  34. snprintf( msg, sizeof( msg ), "%d", i );
  35. Add( aL.CPoint( i ), msg, color );
  36. }
  37. }
  38. void LABEL_MANAGER::Redraw( VIEW_OVERLAY* aOvl )
  39. {
  40. recalculate();
  41. for( auto& lbl : m_labels )
  42. {
  43. aOvl->SetIsFill( false );
  44. aOvl->SetIsStroke( true );
  45. aOvl->SetLineWidth( 10000 );
  46. aOvl->SetStrokeColor( lbl.m_color.Brighten( 0.7 ) );
  47. aOvl->Rectangle( lbl.m_bbox.GetOrigin(), lbl.m_bbox.GetEnd() );
  48. aOvl->BitmapText( lbl.m_msg, lbl.m_bbox.Centre(), ANGLE_HORIZONTAL );
  49. VECTOR2I nearest = nearestBoxCorner( lbl.m_bbox, lbl.m_target );
  50. aOvl->Line( lbl.m_target, nearest );
  51. }
  52. }
  53. VECTOR2I LABEL_MANAGER::nearestBoxCorner( BOX2I b, VECTOR2I p )
  54. {
  55. VECTOR2I ptest[4] = { b.GetPosition(), b.GetPosition() + VECTOR2I( b.GetWidth(), 0 ),
  56. b.GetPosition() + VECTOR2I( b.GetWidth(), b.GetHeight() ),
  57. b.GetPosition() + VECTOR2I( 0, b.GetHeight() ) };
  58. int bestDist = INT_MAX;
  59. VECTOR2I rv;
  60. for( int i = 0; i < 4; i++ )
  61. {
  62. int dist = ( ptest[i] - p ).EuclideanNorm();
  63. if( dist < bestDist )
  64. {
  65. bestDist = dist;
  66. rv = ptest[i];
  67. }
  68. }
  69. return rv;
  70. }
  71. VECTOR2I LABEL_MANAGER::boxMtv( BOX2I b1, BOX2I b2 )
  72. {
  73. VECTOR2I rv( 0, 0 );
  74. b1.Normalize();
  75. b2.Normalize();
  76. if( !b1.Intersects( b2 ) )
  77. return rv;
  78. int bestDist = INT_MAX;
  79. VECTOR2I p[4] = { b2.GetPosition(), b2.GetPosition() + VECTOR2I( b2.GetWidth(), 0 ),
  80. b2.GetPosition() + VECTOR2I( b2.GetWidth(), b2.GetHeight() ),
  81. b2.GetPosition() + VECTOR2I( 0, b2.GetHeight() ) };
  82. for( int i = 0; i < 4; i++ )
  83. {
  84. if( b1.Contains( p[i] ) )
  85. {
  86. // printf("CONT %d\n", i );
  87. VECTOR2I dp[4] = { VECTOR2I( b1.GetEnd().x - p[i].x + 1, 0 ),
  88. VECTOR2I( b1.GetPosition().x - p[i].x - 1, 0 ),
  89. VECTOR2I( 0, b1.GetEnd().y - p[i].y + 1 ),
  90. VECTOR2I( 0, b1.GetPosition().y - p[i].y - 1 ) };
  91. for( int j = 0; j < 4; j++ )
  92. {
  93. BOX2I btest( b2 );
  94. btest.Move( dp[j] );
  95. if( !b1.Intersects( btest ) )
  96. {
  97. int dist = dp[j].EuclideanNorm();
  98. if( dist < bestDist )
  99. {
  100. bestDist = dist;
  101. rv = dp[j];
  102. }
  103. }
  104. }
  105. }
  106. }
  107. return rv;
  108. }
  109. void LABEL_MANAGER::recalculate()
  110. {
  111. int iterLimit = 5;
  112. while( iterLimit > 0 )
  113. {
  114. bool collisionsFound = false;
  115. for( int i = 0; i < m_labels.size(); i++ )
  116. {
  117. for( int j = 0; j < m_labels.size(); j++ )
  118. {
  119. if( i == j )
  120. continue;
  121. auto bb_i = m_labels[i].m_bbox;
  122. auto bb_j = m_labels[j].m_bbox;
  123. bb_i.Inflate( 100000 );
  124. bb_j.Inflate( 100000 );
  125. VECTOR2I mtv = boxMtv( bb_i, bb_j );
  126. if( mtv.x || mtv.y )
  127. {
  128. m_labels[i].m_bbox.Move( -mtv );
  129. collisionsFound = true;
  130. }
  131. }
  132. }
  133. if( !collisionsFound )
  134. break;
  135. iterLimit--;
  136. }
  137. }