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.

646 lines
16 KiB

11 years ago
9 years ago
11 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
11 years ago
9 years ago
11 years ago
11 years ago
9 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
10 years ago
9 years ago
10 years ago
10 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
9 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 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 <base_units.h> // God forgive me doing this...
  22. #include "pns_node.h"
  23. #include "pns_itemset.h"
  24. #include "pns_topology.h"
  25. #include "pns_meander.h"
  26. #include "pns_meander_placer_base.h"
  27. #include "pns_router.h"
  28. #include "pns_debug_decorator.h"
  29. namespace PNS {
  30. const MEANDER_SETTINGS& MEANDER_SHAPE::Settings() const
  31. {
  32. return m_placer->MeanderSettings();
  33. }
  34. const MEANDER_SETTINGS& MEANDERED_LINE::Settings() const
  35. {
  36. return m_placer->MeanderSettings();
  37. }
  38. void MEANDERED_LINE::MeanderSegment( const SEG& aBase, int aBaseIndex )
  39. {
  40. double base_len = aBase.Length();
  41. SHAPE_LINE_CHAIN lc;
  42. bool side = true;
  43. VECTOR2D dir( aBase.B - aBase.A );
  44. if( !m_dual )
  45. AddCorner( aBase.A );
  46. bool turning = false;
  47. bool started = false;
  48. m_last = aBase.A;
  49. do
  50. {
  51. MEANDER_SHAPE m( m_placer, m_width, m_dual );
  52. m.SetBaselineOffset( m_baselineOffset );
  53. m.SetBaseIndex( aBaseIndex );
  54. double thr = (double) m.spacing();
  55. bool fail = false;
  56. double remaining = base_len - ( m_last - aBase.A ).EuclideanNorm();
  57. if( remaining < Settings( ).m_step )
  58. break;
  59. if( remaining > 3.0 * thr )
  60. {
  61. if( !turning )
  62. {
  63. for( int i = 0; i < 2; i++ )
  64. {
  65. if( m.Fit( MT_CHECK_START, aBase, m_last, i ) )
  66. {
  67. turning = true;
  68. AddMeander( new MEANDER_SHAPE( m ) );
  69. side = !i;
  70. started = true;
  71. break;
  72. }
  73. }
  74. if( !turning )
  75. {
  76. fail = true;
  77. for( int i = 0; i < 2; i++ )
  78. {
  79. if( m.Fit( MT_SINGLE, aBase, m_last, i ) )
  80. {
  81. AddMeander( new MEANDER_SHAPE( m ) );
  82. fail = false;
  83. started = false;
  84. side = !i;
  85. break;
  86. }
  87. }
  88. }
  89. } else {
  90. bool rv = m.Fit( MT_CHECK_FINISH, aBase, m_last, side );
  91. if( rv )
  92. {
  93. m.Fit( MT_TURN, aBase, m_last, side );
  94. AddMeander( new MEANDER_SHAPE( m ) );
  95. started = true;
  96. } else {
  97. m.Fit( MT_FINISH, aBase, m_last, side );
  98. started = false;
  99. AddMeander( new MEANDER_SHAPE( m ) );
  100. turning = false;
  101. }
  102. side = !side;
  103. }
  104. } else if( started )
  105. {
  106. bool rv = m.Fit( MT_FINISH, aBase, m_last, side );
  107. if( rv )
  108. AddMeander( new MEANDER_SHAPE( m ) );
  109. break;
  110. } else {
  111. fail = true;
  112. }
  113. remaining = base_len - ( m_last - aBase.A ).EuclideanNorm( );
  114. if( remaining < Settings( ).m_step )
  115. break;
  116. if( fail )
  117. {
  118. MEANDER_SHAPE tmp( m_placer, m_width, m_dual );
  119. tmp.SetBaselineOffset( m_baselineOffset );
  120. tmp.SetBaseIndex( aBaseIndex );
  121. int nextP = tmp.spacing() - 2 * tmp.cornerRadius() + Settings().m_step;
  122. VECTOR2I pn = m_last + dir.Resize( nextP );
  123. if( aBase.Contains( pn ) && !m_dual )
  124. {
  125. AddCorner( pn );
  126. } else
  127. break;
  128. }
  129. } while( true );
  130. if( !m_dual )
  131. AddCorner( aBase.B );
  132. }
  133. int MEANDER_SHAPE::cornerRadius() const
  134. {
  135. // TODO: fix diff-pair meandering so we can use non-100% radii
  136. int rPercent = m_dual ? 100 : Settings().m_cornerRadiusPercentage;
  137. return (int64_t) spacing() * rPercent / 200;
  138. }
  139. int MEANDER_SHAPE::spacing( ) const
  140. {
  141. if( !m_dual )
  142. return std::max( 2 * m_width, Settings().m_spacing );
  143. else
  144. {
  145. int sp = 2 * ( m_width + std::abs( m_baselineOffset ) );
  146. return std::max( sp, Settings().m_spacing );
  147. }
  148. }
  149. SHAPE_LINE_CHAIN MEANDER_SHAPE::makeMiterShape( VECTOR2D aP, VECTOR2D aDir, bool aSide )
  150. {
  151. SHAPE_LINE_CHAIN lc;
  152. if( aDir.EuclideanNorm( ) == 0.0f )
  153. {
  154. lc.Append( aP );
  155. return lc;
  156. }
  157. VECTOR2D dir_u( aDir );
  158. VECTOR2D dir_v( aDir.Perpendicular( ) );
  159. VECTOR2D p = aP;
  160. lc.Append( ( int ) p.x, ( int ) p.y );
  161. // fixme: refactor
  162. switch( m_placer->MeanderSettings().m_cornerStyle )
  163. {
  164. case MEANDER_STYLE_ROUND:
  165. {
  166. const int ArcSegments = Settings().m_cornerArcSegments;
  167. double radius = (double) aDir.EuclideanNorm();
  168. double angleStep = M_PI / 2.0 / (double) ArcSegments;
  169. double correction = 12.0 * radius * ( 1.0 - cos( angleStep / 2.0 ) );
  170. if( !m_dual )
  171. correction = 0.0;
  172. else if( radius < m_meanCornerRadius )
  173. correction = 0.0;
  174. VECTOR2D dir_uu = dir_u.Resize( radius - correction );
  175. VECTOR2D dir_vv = dir_v.Resize( radius - correction );
  176. VECTOR2D shift = dir_u.Resize( correction );
  177. for( int i = ArcSegments - 1; i >= 0; i-- )
  178. {
  179. double alpha = (double) i / (double) ( ArcSegments - 1 ) * M_PI / 2.0;
  180. p = aP + shift + dir_uu * cos( alpha ) + dir_vv * ( aSide ? -1.0 : 1.0 ) * ( 1.0 - sin( alpha ) );
  181. lc.Append( ( int ) p.x, ( int ) p.y );
  182. }
  183. }
  184. break;
  185. case MEANDER_STYLE_CHAMFER:
  186. {
  187. double radius = (double) aDir.EuclideanNorm();
  188. double correction = 0;
  189. if( m_dual && radius > m_meanCornerRadius )
  190. correction = (double)(-2 * abs(m_baselineOffset)) * tan( 22.5 * M_PI / 180.0 );
  191. VECTOR2D dir_cu = dir_u.Resize( correction );
  192. VECTOR2D dir_cv = dir_v.Resize( correction );
  193. p = aP - dir_cu;
  194. lc.Append( ( int ) p.x, ( int ) p.y );
  195. p = aP + dir_u + (dir_v + dir_cv) * ( aSide ? -1.0 : 1.0 );
  196. lc.Append( ( int ) p.x, ( int ) p.y );
  197. break;
  198. }
  199. }
  200. p = aP + dir_u + dir_v * ( aSide ? -1.0 : 1.0 );
  201. lc.Append( ( int ) p.x, ( int ) p.y );
  202. return lc;
  203. }
  204. VECTOR2I MEANDER_SHAPE::reflect( VECTOR2I p, const SEG& line )
  205. {
  206. typedef int64_t ecoord;
  207. VECTOR2I d = line.B - line.A;
  208. ecoord l_squared = d.Dot( d );
  209. ecoord t = d.Dot( p - line.A );
  210. VECTOR2I c, rv;
  211. if( !l_squared )
  212. c = p;
  213. else {
  214. c.x = line.A.x + rescale( t, (ecoord) d.x, l_squared );
  215. c.y = line.A.y + rescale( t, (ecoord) d.y, l_squared );
  216. }
  217. return 2 * c - p;
  218. }
  219. void MEANDER_SHAPE::start( SHAPE_LINE_CHAIN* aTarget, const VECTOR2D& aWhere, const VECTOR2D& aDir )
  220. {
  221. m_currentTarget = aTarget;
  222. m_currentTarget->Clear();
  223. m_currentTarget->Append( aWhere );
  224. m_currentDir = aDir;
  225. m_currentPos = aWhere;
  226. }
  227. void MEANDER_SHAPE::forward( int aLength )
  228. {
  229. m_currentPos += m_currentDir.Resize( aLength );
  230. m_currentTarget->Append( m_currentPos );
  231. }
  232. void MEANDER_SHAPE::turn( int aAngle )
  233. {
  234. m_currentDir = m_currentDir.Rotate( (double) aAngle * M_PI / 180.0 );
  235. }
  236. void MEANDER_SHAPE::miter( int aRadius, bool aSide )
  237. {
  238. if( aRadius <= 0 )
  239. {
  240. turn( aSide ? -90 : 90 );
  241. return;
  242. }
  243. VECTOR2D dir = m_currentDir.Resize( (double) aRadius );
  244. SHAPE_LINE_CHAIN lc = makeMiterShape( m_currentPos, dir, aSide );
  245. m_currentPos = lc.CPoint( -1 );
  246. m_currentDir = dir.Rotate( aSide ? -M_PI / 2.0 : M_PI / 2.0 );
  247. m_currentTarget->Append( lc );
  248. }
  249. void MEANDER_SHAPE::uShape( int aSides, int aCorner, int aTop )
  250. {
  251. forward( aSides );
  252. miter( aCorner, true );
  253. forward( aTop );
  254. miter( aCorner, true );
  255. forward( aSides );
  256. }
  257. SHAPE_LINE_CHAIN MEANDER_SHAPE::genMeanderShape( VECTOR2D aP, VECTOR2D aDir,
  258. bool aSide, MEANDER_TYPE aType, int aAmpl, int aBaselineOffset )
  259. {
  260. const MEANDER_SETTINGS& st = Settings();
  261. int cr = cornerRadius();
  262. int offset = aBaselineOffset;
  263. int spc = spacing();
  264. if( aSide )
  265. offset *= -1;
  266. VECTOR2D dir_u_b( aDir.Resize( offset ) );
  267. VECTOR2D dir_v_b( dir_u_b.Perpendicular() );
  268. if( 2 * cr > aAmpl )
  269. {
  270. cr = aAmpl / 2;
  271. }
  272. if( 2 * cr > spc )
  273. {
  274. cr = spc / 2;
  275. }
  276. m_meanCornerRadius = cr;
  277. SHAPE_LINE_CHAIN lc;
  278. start( &lc, aP + dir_v_b, aDir );
  279. switch( aType )
  280. {
  281. case MT_EMPTY:
  282. {
  283. lc.Append( aP + dir_v_b + aDir );
  284. break;
  285. }
  286. case MT_START:
  287. {
  288. miter( cr - offset, false );
  289. uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
  290. forward( std::min( cr - offset, cr + offset ) );
  291. forward( std::abs( offset ) );
  292. break;
  293. }
  294. case MT_FINISH:
  295. {
  296. start( &lc, aP - dir_u_b, aDir );
  297. turn( 90 );
  298. forward( std::min( cr - offset, cr + offset ) );
  299. forward( std::abs( offset ) );
  300. uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
  301. miter( cr - offset, false );
  302. break;
  303. }
  304. case MT_TURN:
  305. {
  306. start( &lc, aP - dir_u_b, aDir );
  307. turn( 90 );
  308. forward( std::abs( offset ) );
  309. uShape( aAmpl - cr, cr + offset, spc - 2 * cr );
  310. forward( std::abs( offset ) );
  311. break;
  312. }
  313. case MT_SINGLE:
  314. {
  315. miter( cr - offset, false );
  316. uShape( aAmpl - 2 * cr + std::abs( offset ), cr + offset, spc - 2 * cr );
  317. miter( cr - offset, false );
  318. lc.Append( aP + dir_v_b + aDir.Resize( 2 * st.m_spacing ) );
  319. break;
  320. }
  321. default:
  322. break;
  323. }
  324. if( aSide )
  325. {
  326. SEG axis( aP, aP + aDir );
  327. for( int i = 0; i < lc.PointCount(); i++ )
  328. lc.Point( i ) = reflect( lc.CPoint( i ), axis );
  329. }
  330. return lc;
  331. }
  332. bool MEANDERED_LINE::CheckSelfIntersections( MEANDER_SHAPE* aShape, int aClearance )
  333. {
  334. for( int i = m_meanders.size() - 1; i >= 0; i-- )
  335. {
  336. MEANDER_SHAPE* m = m_meanders[i];
  337. if( m->Type() == MT_EMPTY || m->Type() == MT_CORNER )
  338. continue;
  339. const SEG& b1 = aShape->BaseSegment();
  340. const SEG& b2 = m->BaseSegment();
  341. if( b1.ApproxParallel( b2 ) )
  342. continue;
  343. int n = m->CLine( 0 ).SegmentCount();
  344. for( int j = n - 1; j >= 0; j-- )
  345. if( aShape->CLine( 0 ).Collide( m->CLine( 0 ) .CSegment( j ), aClearance ) )
  346. return false;
  347. }
  348. return true;
  349. }
  350. bool MEANDER_SHAPE::Fit( MEANDER_TYPE aType, const SEG& aSeg, const VECTOR2I& aP, bool aSide )
  351. {
  352. const MEANDER_SETTINGS& st = Settings();
  353. bool checkMode = false;
  354. MEANDER_TYPE prim1, prim2;
  355. if( aType == MT_CHECK_START )
  356. {
  357. prim1 = MT_START;
  358. prim2 = MT_TURN;
  359. checkMode = true;
  360. }
  361. else if( aType == MT_CHECK_FINISH )
  362. {
  363. prim1 = MT_TURN;
  364. prim2 = MT_FINISH;
  365. checkMode = true;
  366. }
  367. if( checkMode )
  368. {
  369. MEANDER_SHAPE m1( m_placer, m_width, m_dual );
  370. MEANDER_SHAPE m2( m_placer, m_width, m_dual );
  371. m1.SetBaselineOffset( m_baselineOffset );
  372. m2.SetBaselineOffset( m_baselineOffset );
  373. bool c1 = m1.Fit( prim1, aSeg, aP, aSide );
  374. bool c2 = false;
  375. if( c1 )
  376. c2 = m2.Fit( prim2, aSeg, m1.End(), !aSide );
  377. if( c1 && c2 )
  378. {
  379. m_type = prim1;
  380. m_shapes[0] = m1.m_shapes[0];
  381. m_shapes[1] = m1.m_shapes[1];
  382. m_baseSeg =aSeg;
  383. m_p0 = aP;
  384. m_side = aSide;
  385. m_amplitude = m1.Amplitude();
  386. m_dual = m1.m_dual;
  387. m_baseSeg = m1.m_baseSeg;
  388. m_baseIndex = m1.m_baseIndex;
  389. updateBaseSegment();
  390. m_baselineOffset = m1.m_baselineOffset;
  391. return true;
  392. } else
  393. return false;
  394. }
  395. int minAmpl = st.m_minAmplitude;
  396. int maxAmpl = st.m_maxAmplitude;
  397. if( m_dual )
  398. {
  399. minAmpl = std::max( minAmpl, 2 * std::abs( m_baselineOffset ) );
  400. maxAmpl = std::max( maxAmpl, 2 * std::abs( m_baselineOffset ) );
  401. }
  402. for( int ampl = maxAmpl; ampl >= minAmpl; ampl -= st.m_step )
  403. {
  404. if( m_dual )
  405. {
  406. m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, m_baselineOffset );
  407. m_shapes[1] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, -m_baselineOffset );
  408. }
  409. else
  410. {
  411. m_shapes[0] = genMeanderShape( aP, aSeg.B - aSeg.A, aSide, aType, ampl, 0 );
  412. }
  413. m_type = aType;
  414. m_baseSeg = aSeg;
  415. m_p0 = aP;
  416. m_side = aSide;
  417. m_amplitude = ampl;
  418. updateBaseSegment();
  419. if( m_placer->CheckFit( this ) )
  420. return true;
  421. }
  422. return false;
  423. }
  424. void MEANDER_SHAPE::Recalculate()
  425. {
  426. m_shapes[0] = genMeanderShape( m_p0, m_baseSeg.B - m_baseSeg.A, m_side, m_type, m_amplitude, m_dual ? m_baselineOffset : 0 );
  427. if( m_dual )
  428. m_shapes[1] = genMeanderShape( m_p0, m_baseSeg.B - m_baseSeg.A, m_side, m_type, m_amplitude, -m_baselineOffset );
  429. updateBaseSegment();
  430. }
  431. void MEANDER_SHAPE::Resize( int aAmpl )
  432. {
  433. if( aAmpl < 0 )
  434. return;
  435. m_amplitude = aAmpl;
  436. Recalculate();
  437. }
  438. void MEANDER_SHAPE::MakeEmpty()
  439. {
  440. updateBaseSegment();
  441. VECTOR2I dir = m_clippedBaseSeg.B - m_clippedBaseSeg.A;
  442. m_type = MT_EMPTY;
  443. m_shapes[0] = genMeanderShape( m_p0, dir, m_side, m_type, 0, m_dual ? m_baselineOffset : 0 );
  444. if( m_dual )
  445. m_shapes[1] = genMeanderShape( m_p0, dir, m_side, m_type, 0, -m_baselineOffset );
  446. }
  447. void MEANDERED_LINE::AddCorner( const VECTOR2I& aA, const VECTOR2I& aB )
  448. {
  449. MEANDER_SHAPE* m = new MEANDER_SHAPE( m_placer, m_width, m_dual );
  450. m->MakeCorner( aA, aB );
  451. m_last = aA;
  452. m_meanders.push_back( m );
  453. }
  454. void MEANDER_SHAPE::MakeCorner( VECTOR2I aP1, VECTOR2I aP2 )
  455. {
  456. SetType( MT_CORNER );
  457. m_shapes[0].Clear();
  458. m_shapes[1].Clear();
  459. m_shapes[0].Append( aP1 );
  460. m_shapes[1].Append( aP2 );
  461. m_clippedBaseSeg.A = aP1;
  462. m_clippedBaseSeg.B = aP1;
  463. }
  464. void MEANDERED_LINE::AddMeander( MEANDER_SHAPE* aShape )
  465. {
  466. m_last = aShape->BaseSegment().B;
  467. m_meanders.push_back( aShape );
  468. }
  469. void MEANDERED_LINE::Clear()
  470. {
  471. for( MEANDER_SHAPE* m : m_meanders )
  472. {
  473. delete m;
  474. }
  475. m_meanders.clear( );
  476. }
  477. int MEANDER_SHAPE::BaselineLength() const
  478. {
  479. return m_clippedBaseSeg.Length();
  480. }
  481. int MEANDER_SHAPE::MaxTunableLength() const
  482. {
  483. return CLine( 0 ).Length();
  484. }
  485. void MEANDER_SHAPE::updateBaseSegment( )
  486. {
  487. if( m_dual )
  488. {
  489. VECTOR2I midpA = ( CLine( 0 ).CPoint( 0 ) + CLine( 1 ).CPoint( 0 ) ) / 2;
  490. VECTOR2I midpB = ( CLine( 0 ).CPoint( -1 ) + CLine( 1 ).CPoint( -1 ) ) / 2;
  491. m_clippedBaseSeg.A = m_baseSeg.LineProject( midpA );
  492. m_clippedBaseSeg.B = m_baseSeg.LineProject( midpB );
  493. }
  494. else
  495. {
  496. m_clippedBaseSeg.A = m_baseSeg.LineProject( CLine( 0 ).CPoint( 0 ) );
  497. m_clippedBaseSeg.B = m_baseSeg.LineProject( CLine( 0 ).CPoint( -1 ) );
  498. }
  499. }
  500. }