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.

407 lines
11 KiB

11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. /*
  2. * KiRouter - a push-and-(sometimes-)shove PCB router
  3. *
  4. * Copyright (C) 2013-2014 CERN
  5. * Copyright (C) 2016 KiCad Developers, see AUTHORS.txt for contributors.
  6. * Author: Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
  7. *
  8. * This program is free software: you can redistribute it and/or modify it
  9. * under the terms of the GNU General Public License as published by the
  10. * Free Software Foundation, either version 3 of the License, or (at your
  11. * option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful, but
  14. * WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License along
  19. * with this program. If not, see <http://www.gnu.org/licenses/>.
  20. */
  21. #include <deque>
  22. #include <gal/color4d.h>
  23. #include <view/view.h>
  24. #include <geometry/shape_rect.h>
  25. #include <geometry/shape_simple.h>
  26. #include "class_track.h"
  27. #include <pcb_painter.h>
  28. #include "router_preview_item.h"
  29. #include "pns_arc.h"
  30. #include "pns_line.h"
  31. #include "pns_segment.h"
  32. #include "pns_via.h"
  33. using namespace KIGFX;
  34. ROUTER_PREVIEW_ITEM::ROUTER_PREVIEW_ITEM( const PNS::ITEM* aItem, KIGFX::VIEW* aView ) :
  35. EDA_ITEM( NOT_USED )
  36. {
  37. m_view = aView;
  38. m_shape = NULL;
  39. m_clearance = -1;
  40. m_originLayer = m_layer = LAYER_SELECT_OVERLAY ;
  41. m_showTrackClearance = false;
  42. m_showViaClearance = false;
  43. // initialize variables, overwritten by Update( aItem ), if aItem != NULL
  44. m_router = NULL;
  45. m_type = PR_SHAPE;
  46. m_style = 0;
  47. m_width = 0;
  48. m_depth = 0;
  49. if( aItem )
  50. Update( aItem );
  51. }
  52. ROUTER_PREVIEW_ITEM::~ROUTER_PREVIEW_ITEM()
  53. {
  54. delete m_shape;
  55. }
  56. void ROUTER_PREVIEW_ITEM::Update( const PNS::ITEM* aItem )
  57. {
  58. m_originLayer = aItem->Layers().Start();
  59. if( aItem->OfKind( PNS::ITEM::LINE_T ) )
  60. {
  61. const PNS::LINE* l = static_cast<const PNS::LINE*>( aItem );
  62. if( !l->SegmentCount() )
  63. return;
  64. }
  65. assert( m_originLayer >= 0 );
  66. m_layer = m_originLayer;
  67. m_color = getLayerColor( m_originLayer );
  68. m_color.a = 0.8;
  69. m_depth = BaseOverlayDepth - aItem->Layers().Start();
  70. m_shape = aItem->Shape()->Clone();
  71. switch( aItem->Kind() )
  72. {
  73. case PNS::ITEM::LINE_T:
  74. m_type = PR_SHAPE;
  75. m_width = static_cast<const PNS::LINE*>( aItem )->Width();
  76. break;
  77. case PNS::ITEM::ARC_T:
  78. m_type = PR_SHAPE;
  79. m_width = static_cast<const PNS::ARC*>( aItem )->Width();
  80. break;
  81. case PNS::ITEM::SEGMENT_T:
  82. m_type = PR_SHAPE;
  83. m_width = static_cast<const PNS::SEGMENT*>( aItem )->Width();
  84. break;
  85. case PNS::ITEM::VIA_T:
  86. m_originLayer = m_layer = LAYER_VIAS;
  87. m_type = PR_SHAPE;
  88. m_width = 0;
  89. m_color = COLOR4D( 0.7, 0.7, 0.7, 0.8 );
  90. m_depth = ViaOverlayDepth;
  91. break;
  92. case PNS::ITEM::SOLID_T:
  93. m_type = PR_SHAPE;
  94. m_width = 0;
  95. break;
  96. default:
  97. break;
  98. }
  99. if( aItem->Marker() & PNS::MK_VIOLATION )
  100. m_color = COLOR4D( 0, 1, 0, 1 );
  101. }
  102. const BOX2I ROUTER_PREVIEW_ITEM::ViewBBox() const
  103. {
  104. BOX2I bbox;
  105. switch( m_type )
  106. {
  107. case PR_SHAPE:
  108. if( m_shape )
  109. {
  110. bbox = m_shape->BBox();
  111. bbox.Inflate( m_width / 2 );
  112. }
  113. return bbox;
  114. case PR_POINT:
  115. bbox = BOX2I ( m_pos - VECTOR2I( 100000, 100000 ), VECTOR2I( 200000, 200000 ) );
  116. return bbox;
  117. default:
  118. break;
  119. }
  120. return bbox;
  121. }
  122. void ROUTER_PREVIEW_ITEM::drawLineChain( const SHAPE_LINE_CHAIN& aL, KIGFX::GAL* gal ) const
  123. {
  124. gal->SetIsFill( false );
  125. for( int s = 0; s < aL.SegmentCount(); s++ )
  126. gal->DrawLine( aL.CSegment( s ).A, aL.CSegment( s ).B );
  127. for( size_t s = 0; s < aL.ArcCount(); s++ )
  128. {
  129. auto arc = aL.CArcs()[s];
  130. auto start_angle = DEG2RAD( arc.GetStartAngle() );
  131. auto angle = DEG2RAD( arc.GetCentralAngle() );
  132. gal->DrawArc( arc.GetCenter(), arc.GetRadius(), start_angle, start_angle + angle);
  133. }
  134. if( aL.IsClosed() )
  135. gal->DrawLine( aL.CSegment( -1 ).B, aL.CSegment( 0 ).A );
  136. }
  137. void ROUTER_PREVIEW_ITEM::ViewDraw( int aLayer, KIGFX::VIEW* aView ) const
  138. {
  139. auto gal = aView->GetGAL();
  140. //col.Brighten(0.7);
  141. if( m_type == PR_SHAPE )
  142. {
  143. if( !m_shape )
  144. return;
  145. // N.B. The order of draw here is important
  146. // Cairo doesn't current support z-ordering, so we need
  147. // to draw the clearance first to ensure it is in the background
  148. gal->SetLayerDepth( ClearanceOverlayDepth );
  149. //TODO(snh) Add configuration option for the color/alpha here
  150. gal->SetStrokeColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.9 ) );
  151. gal->SetFillColor( COLOR4D( DARKDARKGRAY ).WithAlpha( 0.7 ) );
  152. gal->SetIsStroke( m_width ? true : false );
  153. gal->SetIsFill( true );
  154. switch( m_shape->Type() )
  155. {
  156. case SH_LINE_CHAIN:
  157. {
  158. const SHAPE_LINE_CHAIN* l = (const SHAPE_LINE_CHAIN*) m_shape;
  159. if( m_showTrackClearance && m_clearance > 0 )
  160. {
  161. gal->SetLineWidth( m_width + 2 * m_clearance );
  162. drawLineChain( *l, gal );
  163. }
  164. gal->SetLayerDepth( m_depth );
  165. gal->SetLineWidth( m_width );
  166. gal->SetStrokeColor( m_color );
  167. gal->SetFillColor( m_color );
  168. drawLineChain( *l, gal );
  169. break;
  170. }
  171. case SH_SEGMENT:
  172. {
  173. const SHAPE_SEGMENT* s = (const SHAPE_SEGMENT*) m_shape;
  174. if( m_showTrackClearance && m_clearance > 0 )
  175. {
  176. gal->SetLineWidth( m_width + 2 * m_clearance );
  177. gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() + 2 * m_clearance );
  178. }
  179. gal->SetLayerDepth( m_depth );
  180. gal->SetLineWidth( m_width );
  181. gal->SetStrokeColor( m_color );
  182. gal->SetFillColor( m_color );
  183. gal->DrawSegment( s->GetSeg().A, s->GetSeg().B, s->GetWidth() );
  184. break;
  185. }
  186. case SH_CIRCLE:
  187. {
  188. const SHAPE_CIRCLE* c = (const SHAPE_CIRCLE*) m_shape;
  189. gal->SetStrokeColor( m_color );
  190. if( m_showViaClearance && m_clearance > 0 )
  191. {
  192. gal->SetIsStroke( false );
  193. gal->DrawCircle( c->GetCenter(), c->GetRadius() + m_clearance );
  194. }
  195. gal->SetLayerDepth( m_depth );
  196. gal->SetIsStroke( m_width ? true : false );
  197. gal->SetLineWidth( m_width );
  198. gal->SetFillColor( m_color );
  199. gal->DrawCircle( c->GetCenter(), c->GetRadius() );
  200. break;
  201. }
  202. case SH_RECT:
  203. {
  204. const SHAPE_RECT* r = (const SHAPE_RECT*) m_shape;
  205. gal->SetFillColor( m_color );
  206. if( m_clearance > 0 )
  207. {
  208. VECTOR2I p0( r->GetPosition() ), s( r->GetSize() );
  209. gal->SetIsStroke( true );
  210. gal->SetLineWidth( 2 * m_clearance );
  211. gal->DrawLine( p0, VECTOR2I( p0.x + s.x, p0.y ) );
  212. gal->DrawLine( p0, VECTOR2I( p0.x, p0.y + s.y ) );
  213. gal->DrawLine( p0 + s , VECTOR2I( p0.x + s.x, p0.y ) );
  214. gal->DrawLine( p0 + s, VECTOR2I( p0.x, p0.y + s.y ) );
  215. }
  216. gal->SetLayerDepth( m_depth );
  217. gal->SetIsStroke( m_width ? true : false );
  218. gal->SetLineWidth( m_width );
  219. gal->SetStrokeColor( m_color );
  220. gal->DrawRectangle( r->GetPosition(), r->GetPosition() + r->GetSize() );
  221. break;
  222. }
  223. case SH_SIMPLE:
  224. {
  225. const SHAPE_SIMPLE* c = (const SHAPE_SIMPLE*) m_shape;
  226. std::deque<VECTOR2D> polygon = std::deque<VECTOR2D>();
  227. for( int i = 0; i < c->PointCount(); i++ )
  228. {
  229. polygon.push_back( c->CDPoint( i ) );
  230. }
  231. gal->SetFillColor( m_color );
  232. if( m_clearance > 0 )
  233. {
  234. gal->SetIsStroke( true );
  235. gal->SetLineWidth( 2 * m_clearance );
  236. // need the implicit last segment to be explicit for DrawPolyline
  237. polygon.push_back( c->CDPoint( 0 ) );
  238. gal->DrawPolyline( polygon );
  239. }
  240. gal->SetLayerDepth( m_depth );
  241. gal->SetIsStroke( m_width ? true : false );
  242. gal->SetLineWidth( m_width );
  243. gal->SetStrokeColor( m_color );
  244. gal->DrawPolygon( polygon );
  245. break;
  246. }
  247. case SH_ARC:
  248. {
  249. const auto arc = static_cast<const SHAPE_ARC*>( m_shape );
  250. auto start_angle = DEG2RAD( arc->GetStartAngle() );
  251. auto angle = DEG2RAD( arc->GetCentralAngle() );
  252. gal->SetIsFill( false );
  253. gal->SetIsStroke( true );
  254. if( m_showTrackClearance && m_clearance > 0 )
  255. {
  256. gal->SetLineWidth( m_width + 2 * m_clearance );
  257. gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
  258. }
  259. gal->SetLayerDepth( m_depth );
  260. gal->SetStrokeColor( m_color );
  261. gal->SetFillColor( m_color );
  262. gal->SetLineWidth( m_width );
  263. gal->DrawArc( arc->GetCenter(), arc->GetRadius(), start_angle, start_angle + angle );
  264. break;
  265. }
  266. case SH_POLY_SET:
  267. case SH_COMPOUND:
  268. break; // Not yet in use
  269. }
  270. }
  271. }
  272. void ROUTER_PREVIEW_ITEM::Line( const SHAPE_LINE_CHAIN& aLine, int aWidth, int aStyle )
  273. {
  274. m_width = aWidth;
  275. m_color = assignColor( aStyle );
  276. m_type = PR_SHAPE;
  277. m_depth = -1024; // TODO gal->GetMinDepth()
  278. m_shape = aLine.Clone();
  279. }
  280. void ROUTER_PREVIEW_ITEM::Point( const VECTOR2I& aPos, int aStyle )
  281. {
  282. }
  283. void ROUTER_PREVIEW_ITEM::Box( const BOX2I& aBox, int aStyle )
  284. {
  285. }
  286. const COLOR4D ROUTER_PREVIEW_ITEM::getLayerColor( int aLayer ) const
  287. {
  288. auto settings = static_cast<PCB_RENDER_SETTINGS*>( m_view->GetPainter()->GetSettings() );
  289. return settings->GetLayerColor( aLayer );
  290. }
  291. const COLOR4D ROUTER_PREVIEW_ITEM::assignColor( int aStyle ) const
  292. {
  293. COLOR4D color;
  294. switch( aStyle )
  295. {
  296. case 0:
  297. color = COLOR4D( 0, 1, 0, 1 ); break;
  298. case 1:
  299. color = COLOR4D( 1, 0, 0, 1 ); break;
  300. case 2:
  301. color = COLOR4D( 1, 1, 0, 1 ); break;
  302. case 3:
  303. color = COLOR4D( 0, 0, 1, 1 ); break;
  304. case 4:
  305. color = COLOR4D( 1, 1, 1, 1 ); break;
  306. case 5:
  307. color = COLOR4D( 1, 1, 0, 1 ); break;
  308. case 6:
  309. color = COLOR4D( 0, 1, 1, 1 ); break;
  310. case 32:
  311. color = COLOR4D( 0, 0, 1, 1 ); break;
  312. default:
  313. color = COLOR4D( 0.4, 0.4, 0.4, 1 ); break;
  314. }
  315. return color;
  316. }
  317. const int ROUTER_PREVIEW_ITEM::ClearanceOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 10;
  318. const int ROUTER_PREVIEW_ITEM::BaseOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 20;
  319. const int ROUTER_PREVIEW_ITEM::ViaOverlayDepth = -VIEW::VIEW_MAX_LAYERS - 50;