Rework Copper Sliver check

Adds QA checks to copper sliver tests.  Adds the following checks:
- Dot product between two arms (quickly avoids checks for >90°)
- Checks the sliver is convex (area test)
- Eliminates minor slivers with angles that are approximately 0 and ones
  with the opposite side width beneath a configurable level
- Updates Clipper2 to fix a couple of jagged edges on inflate
- Adds simplify during zone fill inflation to limit jaggies

Fixes https://gitlab.com/kicad/code/kicad/issues/14549
This commit is contained in:
Seth Hillbrand 2023-04-25 10:26:03 -07:00
parent dd6e3c0432
commit f7f52d77e4
20 changed files with 93308 additions and 186 deletions

View File

@ -1009,7 +1009,7 @@ public:
* #ROUND_ALL_CORNERS to round regardless of angles
*/
void Inflate( int aAmount, int aCircleSegCount,
CORNER_STRATEGY aCornerStrategy = ROUND_ALL_CORNERS );
CORNER_STRATEGY aCornerStrategy = ROUND_ALL_CORNERS, bool aSimplify = false );
void Deflate( int aAmount, int aCircleSegmentsCount,
CORNER_STRATEGY aCornerStrategy = CHAMFER_ALL_CORNERS )
@ -1402,7 +1402,7 @@ private:
const std::vector<SHAPE_ARC>& aArcBuffer );
void inflate1( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy );
void inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy );
void inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy, bool aSimplify = false );
/**
* This is the engine to execute all polygon boolean transforms (AND, OR, ... and polygon

View File

@ -992,7 +992,8 @@ void SHAPE_POLY_SET::inflate1( int aAmount, int aCircleSegCount, CORNER_STRATEGY
}
void SHAPE_POLY_SET::inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy )
void SHAPE_POLY_SET::inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy,
bool aSimplify )
{
using namespace Clipper2Lib;
// A static table to avoid repetitive calculations of the coefficient
@ -1071,17 +1072,35 @@ void SHAPE_POLY_SET::inflate2( int aAmount, int aCircleSegCount, CORNER_STRATEGY
c.MiterLimit( miterLimit );
PolyTree64 tree;
c.Execute( aAmount, tree );
if( aSimplify )
{
Paths64 paths;
c.Execute( aAmount, paths );
Clipper2Lib::SimplifyPaths( paths, std::abs( aAmount ) * coeff, false );
Clipper64 c2;
c2.PreserveCollinear = false;
c2.ReverseSolution = false;
c2.AddSubject( paths );
c2.Execute(ClipType::Union, FillRule::Positive, tree);
}
else
{
c.Execute( aAmount, tree );
}
importTree( tree, zValues, arcBuffer );
tree.Clear();
}
void SHAPE_POLY_SET::Inflate( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy )
void SHAPE_POLY_SET::Inflate( int aAmount, int aCircleSegCount, CORNER_STRATEGY aCornerStrategy,
bool aSimplify )
{
if( ADVANCED_CFG::GetCfg().m_UseClipper2 )
inflate2( aAmount, aCircleSegCount, aCornerStrategy );
inflate2( aAmount, aCircleSegCount, aCornerStrategy, aSimplify );
else
inflate1( aAmount, aCircleSegCount, aCornerStrategy );
}

View File

@ -84,9 +84,11 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
if( !reportPhase( _( "Running sliver detection on copper layers..." ) ) )
return false; // DRC cancelled
int widthTolerance = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SliverWidthTolerance );
int64_t widthTolerance = pcbIUScale.mmToIU( ADVANCED_CFG::GetCfg().m_SliverWidthTolerance );
int64_t squared_width = widthTolerance * widthTolerance;
double angleTolerance = ADVANCED_CFG::GetCfg().m_SliverAngleTolerance;
int testLength = widthTolerance / ( 2 * sin( DEG2RAD( angleTolerance / 2 ) ) );
double cosangleTol = 2.0 * cos( DEG2RAD( angleTolerance ) );
LSET copperLayerSet = m_drcEngine->GetBoard()->GetEnabledLayers() & LSET::AllCuMask();
LSEQ copperLayers = copperLayerSet.Seq();
int layerCount = copperLayers.size();
@ -130,7 +132,6 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
if( !zone->GetIsRuleArea() )
{
fill = zone->GetFill( layer )->CloneDropTriangulation();
fill.Unfracture( SHAPE_POLY_SET::PM_FAST );
poly.Append( fill );
// Report progress on board zones only. Everything else is
@ -141,7 +142,7 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
else
{
item->TransformShapeToPolygon( poly, layer, 0, ARC_LOW_DEF,
ERROR_OUTSIDE );
ERROR_INSIDE );
}
if( m_drcEngine->IsCancelled() )
@ -154,11 +155,7 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
if( m_drcEngine->IsCancelled() )
return 0;
poly.Simplify( SHAPE_POLY_SET::PM_FAST );
// Sharpen corners
poly.Deflate( widthTolerance / 2, ARC_LOW_DEF,
SHAPE_POLY_SET::ALLOW_ACUTE_CORNERS );
poly.Simplify( SHAPE_POLY_SET::POLYGON_MODE::PM_FAST );
return 1;
};
@ -183,7 +180,6 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
}
}
for( int ii = 0; ii < layerCount; ++ii )
{
PCB_LAYER_ID layer = copperLayers[ii];
@ -203,31 +199,78 @@ bool DRC_TEST_PROVIDER_SLIVER_CHECKER::Run()
{
const std::vector<VECTOR2I>& pts = poly.Outline( jj ).CPoints();
int ptCount = pts.size();
int offset = 0;
for( int kk = 0; kk < ptCount; ++kk )
{
VECTOR2I pt = pts[ kk ];
VECTOR2I ptPrior = pts[ ( ptCount + kk - 1 ) % ptCount ];
VECTOR2I vPrior = ( ptPrior - pt );
if( std::abs( vPrior.x ) < min_len && std::abs( vPrior.y ) < min_len && ptCount > 5)
auto area = [&]( const VECTOR2I& p, const VECTOR2I& q, const VECTOR2I& r ) -> VECTOR2I::extended_type
{
ptPrior = pts[ ( ptCount + kk - 2 ) % ptCount ];
return static_cast<VECTOR2I::extended_type>( q.y - p.y ) * ( r.x - q.x ) -
static_cast<VECTOR2I::extended_type>( q.x - p.x ) * ( r.y - q.y );
};
auto isLocallyInside = [&]( int aA, int aB ) -> bool
{
int prev = ( ptCount + aA - 1 ) % ptCount;
int next = ( aA + 1 ) % ptCount;
if( area( pts[prev], pts[aA], pts[next] ) < 0 )
return area( pts[aA], pts[aB], pts[next] ) >= 0 && area( pts[aA], pts[prev], pts[aB] ) >= 0;
else
return area( pts[aA], pts[aB], pts[prev] ) < 0 || area( pts[aA], pts[next], pts[aB] ) < 0;
};
if( ptCount <= 5 )
continue;
for( int kk = 0; kk < ptCount; kk += offset )
{
int prior_index = ( ptCount + kk - 1 ) % ptCount;
int next_index = ( kk + 1 ) % ptCount;
VECTOR2I pt = pts[ kk ];
VECTOR2I ptPrior = pts[ prior_index ];
VECTOR2I vPrior = ( ptPrior - pt );
int forward_offset = 1;
offset = 1;
while( std::abs( vPrior.x ) < min_len && std::abs( vPrior.y ) < min_len
&& offset < ptCount )
{
pt = pts[ ( kk + offset++ ) % ptCount ];
vPrior = ( ptPrior - pt );
}
VECTOR2I ptAfter = pts[ ( kk + 1 ) % ptCount ];
if( offset >= ptCount )
break;
VECTOR2I ptAfter = pts[ next_index ];
VECTOR2I vAfter = ( ptAfter - pt );
if( std::abs( vAfter.x ) < min_len && std::abs( vAfter.y ) < min_len && ptCount > 5 )
while( std::abs( vAfter.x ) < min_len && std::abs( vAfter.y ) < min_len
&& forward_offset < ptCount )
{
ptAfter = pts[ ( kk + 2 ) % ptCount ];
next_index = ( kk + forward_offset++ ) % ptCount;
ptAfter = pts[ next_index ];
vAfter = ( ptAfter - pt );
}
VECTOR2I vIncluded = vPrior.Resize( testLength ) - vAfter.Resize( testLength );
if( offset >= ptCount )
break;
if( vIncluded.SquaredEuclideanNorm() < SEG::Square( widthTolerance ) )
// Negative dot product means that the angle is > 90°
if( vPrior.Dot( vAfter ) <= 0 )
continue;
if( !isLocallyInside( prior_index, next_index ) )
continue;
VECTOR2I vIncluded = ptAfter - ptPrior;
double arm1 = vPrior.SquaredEuclideanNorm();
double arm2 = vAfter.SquaredEuclideanNorm();
double opp = vIncluded.SquaredEuclideanNorm();
double cos_ang = std::abs( ( opp - arm1 - arm2 ) / ( std::sqrt( arm1 ) * std::sqrt( arm2 ) ) );
if( cos_ang > cosangleTol && 2.0 - cos_ang > std::numeric_limits<float>::epsilon() && opp > squared_width )
{
std::shared_ptr<DRC_ITEM> drce = DRC_ITEM::Create( DRCE_COPPER_SLIVER );
drce->SetErrorMessage( drce->GetErrorText() + wxS( " " ) + layerDesc( layer ) );

View File

@ -1551,7 +1551,7 @@ bool ZONE_FILLER::fillCopperZone( const ZONE* aZone, PCB_LAYER_ID aLayer, PCB_LA
*/
if( half_min_width - epsilon > epsilon )
aFillPolys.Inflate( half_min_width - epsilon, numSegs, cornerStrategy );
aFillPolys.Inflate( half_min_width - epsilon, numSegs, cornerStrategy, true );
DUMP_POLYS_TO_COPPER_LAYER( aFillPolys, In15_Cu, wxT( "after-reinflating" ) );

View File

@ -0,0 +1,688 @@
(kicad_pcb (version 20221018) (generator pcbnew)
(general
(thickness 1.6)
)
(paper "A4")
(layers
(0 "F.Cu" signal)
(31 "B.Cu" signal)
(32 "B.Adhes" user "B.Adhesive")
(33 "F.Adhes" user "F.Adhesive")
(34 "B.Paste" user)
(35 "F.Paste" user)
(36 "B.SilkS" user "B.Silkscreen")
(37 "F.SilkS" user "F.Silkscreen")
(38 "B.Mask" user)
(39 "F.Mask" user)
(40 "Dwgs.User" user "User.Drawings")
(41 "Cmts.User" user "User.Comments")
(42 "Eco1.User" user "User.Eco1")
(43 "Eco2.User" user "User.Eco2")
(44 "Edge.Cuts" user)
(45 "Margin" user)
(46 "B.CrtYd" user "B.Courtyard")
(47 "F.CrtYd" user "F.Courtyard")
(48 "B.Fab" user)
(49 "F.Fab" user)
(50 "User.1" user)
(51 "User.2" user)
(52 "User.3" user)
(53 "User.4" user)
(54 "User.5" user)
(55 "User.6" user)
(56 "User.7" user)
(57 "User.8" user)
(58 "User.9" user)
)
(setup
(pad_to_mask_clearance 0)
(pcbplotparams
(layerselection 0x00010fc_ffffffff)
(plot_on_all_layers_selection 0x0000000_00000000)
(disableapertmacros false)
(usegerberextensions false)
(usegerberattributes true)
(usegerberadvancedattributes true)
(creategerberjobfile true)
(dashed_line_dash_ratio 12.000000)
(dashed_line_gap_ratio 3.000000)
(svgprecision 4)
(plotframeref false)
(viasonmask false)
(mode 1)
(useauxorigin false)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15.000000)
(dxfpolygonmode true)
(dxfimperialunits true)
(dxfusepcbnewfont true)
(psnegative false)
(psa4output false)
(plotreference true)
(plotvalue true)
(plotinvisibletext false)
(sketchpadsonfab false)
(subtractmaskfromsilk false)
(outputformat 1)
(mirror false)
(drillshape 1)
(scaleselection 1)
(outputdirectory "")
)
)
(net 0 "")
(footprint "project:C_LOGO" (layer "F.Cu")
(tstamp 710f0618-ba48-4eda-a0d1-184be345cef5)
(at 71 88)
(descr "Test")
(fp_text reference "LOGO101_TOP0" (at 0 0) (layer "F.SilkS") hide
(effects (font (size 1.27 1.27) (thickness 0.15)))
(tstamp 27afe1ea-6789-4aaa-897d-4fc3c0d052d7)
)
(fp_text value "C_LOGO_SCH-28MM7MM" (at 1.1 1.8) (layer "F.Fab") hide
(effects (font (size 1.27 1.27) (thickness 0.15)))
(tstamp 1527b770-c52f-4142-a6cf-1015edd2e0cd)
)
(fp_poly
(pts
(xy 1.011801 -2.635614)
(xy 1.040231 -2.632063)
(xy 1.062153 -2.628414)
(xy 1.114484 -2.617964)
(xy 1.130888 -2.613832)
(xy 1.140922 -2.610495)
(xy 1.154322 -2.607146)
(xy 1.166231 -2.603186)
(xy 1.196375 -2.59312)
(xy 1.196376 -2.593121)
(xy 1.209841 -2.588644)
(xy 1.216539 -2.585294)
(xy 1.226616 -2.581944)
(xy 1.243244 -2.57363)
(xy 1.246795 -2.571847)
(xy 1.256793 -2.568515)
(xy 1.300868 -2.546511)
(xy 1.304229 -2.543124)
(xy 1.310218 -2.540129)
(xy 1.310219 -2.54013)
(xy 1.324241 -2.533145)
(xy 1.327619 -2.529766)
(xy 1.34107 -2.523016)
(xy 1.344392 -2.519692)
(xy 1.351093 -2.516343)
(xy 1.354415 -2.51302)
(xy 1.361141 -2.50967)
(xy 1.364571 -2.506239)
(xy 1.371272 -2.502864)
(xy 1.374568 -2.499567)
(xy 1.381225 -2.496239)
(xy 1.387949 -2.489539)
(xy 1.394693 -2.486168)
(xy 1.404767 -2.476093)
(xy 1.411468 -2.472743)
(xy 1.421544 -2.462666)
(xy 1.42827 -2.459291)
(xy 1.451716 -2.435843)
(xy 1.458418 -2.432493)
(xy 1.5157 -2.375211)
(xy 1.5157 -2.37186)
(xy 1.568935 -2.318626)
(xy 1.277572 -2.103275)
(xy 1.237039 -2.103275)
(xy 1.213193 -2.127121)
(xy 1.177702 -2.15939)
(xy 1.156024 -2.177974)
(xy 1.131596 -2.196284)
(xy 1.112639 -2.208907)
(xy 1.112603 -2.20893)
(xy 1.095077 -2.220621)
(xy 1.079064 -2.228617)
(xy 1.055567 -2.238702)
(xy 1.044024 -2.244473)
(xy 1.028315 -2.249723)
(xy 1.007333 -2.255711)
(xy 0.979896 -2.261798)
(xy 0.962911 -2.264625)
(xy 0.927023 -2.267908)
(xy 0.902462 -2.270975)
(xy 0.898629 -2.270975)
(xy 0.873702 -2.267865)
(xy 0.831115 -2.264567)
(xy 0.774901 -2.25521)
(xy 0.738461 -2.246083)
(xy 0.710951 -2.236928)
(xy 0.686099 -2.227594)
(xy 0.665009 -2.218565)
(xy 0.640725 -2.206423)
(xy 0.61994 -2.194559)
(xy 0.592377 -2.176176)
(xy 0.580657 -2.16738)
(xy 0.562834 -2.153143)
(xy 0.553203 -2.146698)
(xy 0.536833 -2.133073)
(xy 0.523284 -2.119524)
(xy 0.507957 -2.101136)
(xy 0.507981 -2.101164)
(xy 0.491532 -2.0814)
(xy 0.478893 -2.065608)
(xy 0.469291 -2.052813)
(xy 0.46081 -2.041505)
(xy 0.451464 -2.025906)
(xy 0.445795 -2.017413)
(xy 0.440513 -2.006848)
(xy 0.433788 -1.993373)
(xy 0.427038 -1.979923)
(xy 0.415241 -1.956286)
(xy 0.411872 -1.946253)
(xy 0.408546 -1.939575)
(xy 0.406309 -1.932864)
(xy 0.402971 -1.922824)
(xy 0.402959 -1.922789)
(xy 0.396247 -1.902653)
(xy 0.392861 -1.892543)
(xy 0.39286 -1.892543)
(xy 0.390144 -1.884395)
(xy 0.384201 -1.86058)
(xy 0.381082 -1.844958)
(xy 0.381079 -1.844944)
(xy 0.377886 -1.828979)
(xy 0.374763 -1.810219)
(xy 0.371679 -1.788771)
(xy 0.368625 -1.75207)
(xy 0.368625 -1.745348)
(xy 0.365275 -1.705095)
(xy 0.365275 -1.696539)
(xy 0.368625 -1.66634)
(xy 0.368625 -1.662488)
(xy 0.37169 -1.628717)
(xy 0.374904 -1.603174)
(xy 0.378004 -1.581453)
(xy 0.384198 -1.550435)
(xy 0.387257 -1.538202)
(xy 0.387262 -1.538181)
(xy 0.390612 -1.524756)
(xy 0.393481 -1.51328)
(xy 0.396247 -1.505022)
(xy 0.399609 -1.494936)
(xy 0.399621 -1.494901)
(xy 0.402971 -1.484826)
(xy 0.406309 -1.474811)
(xy 0.406321 -1.474776)
(xy 0.408544 -1.46809)
(xy 0.411869 -1.461441)
(xy 0.415245 -1.451361)
(xy 0.41861 -1.444632)
(xy 0.42197 -1.434551)
(xy 0.423755 -1.430969)
(xy 0.430388 -1.417702)
(xy 0.43378 -1.410944)
(xy 0.440513 -1.397477)
(xy 0.44388 -1.390719)
(xy 0.443879 -1.390718)
(xy 0.446917 -1.384642)
(xy 0.4592 -1.372361)
(xy 0.4592 -1.369011)
(xy 0.46255 -1.365661)
(xy 0.46255 -1.362311)
(xy 0.46925 -1.355611)
(xy 0.46925 -1.352206)
(xy 0.47595 -1.345481)
(xy 0.47595 -1.34224)
(xy 0.482675 -1.33554)
(xy 0.482675 -1.332099)
(xy 0.492725 -1.322024)
(xy 0.492725 -1.318711)
(xy 0.5028 -1.308636)
(xy 0.5028 -1.305264)
(xy 0.51955 -1.288483)
(xy 0.51955 -1.285186)
(xy 0.546141 -1.258593)
(xy 0.552843 -1.255243)
(xy 0.566267 -1.241818)
(xy 0.572968 -1.238468)
(xy 0.57964 -1.231794)
(xy 0.586409 -1.228423)
(xy 0.593134 -1.221671)
(xy 0.599793 -1.218343)
(xy 0.603115 -1.21502)
(xy 0.609841 -1.21167)
(xy 0.613218 -1.208292)
(xy 0.620003 -1.2049)
(xy 0.623329 -1.201549)
(xy 0.643393 -1.191518)
(xy 0.64672 -1.188189)
(xy 0.653044 -1.185005)
(xy 0.653043 -1.185004)
(xy 0.659543 -1.181754)
(xy 0.659544 -1.181755)
(xy 0.663125 -1.17997)
(xy 0.673172 -1.176622)
(xy 0.683077 -1.171688)
(xy 0.686681 -1.169885)
(xy 0.696697 -1.166522)
(xy 0.703374 -1.163196)
(xy 0.710086 -1.160959)
(xy 0.710051 -1.160971)
(xy 0.720126 -1.157621)
(xy 0.720161 -1.157609)
(xy 0.730211 -1.154259)
(xy 0.730176 -1.154271)
(xy 0.738485 -1.151507)
(xy 0.750087 -1.148586)
(xy 0.750086 -1.148585)
(xy 0.763406 -1.145262)
(xy 0.763427 -1.145257)
(xy 0.77566 -1.142198)
(xy 0.790495 -1.139236)
(xy 0.809201 -1.136122)
(xy 0.828628 -1.13335)
(xy 0.830717 -1.13335)
(xy 0.900176 -1.12704)
(xy 0.955872 -1.132917)
(xy 0.973704 -1.135886)
(xy 0.988539 -1.138848)
(xy 0.998926 -1.141445)
(xy 1.009003 -1.144796)
(xy 1.022343 -1.14813)
(xy 1.027236 -1.14977)
(xy 1.033984 -1.153144)
(xy 1.04406 -1.156494)
(xy 1.050759 -1.159844)
(xy 1.0608 -1.163182)
(xy 1.071023 -1.168313)
(xy 1.083907 -1.174743)
(xy 1.087284 -1.17812)
(xy 1.100635 -1.18477)
(xy 1.104032 -1.188168)
(xy 1.110816 -1.19156)
(xy 1.114192 -1.19491)
(xy 1.120806 -1.198217)
(xy 1.124103 -1.201514)
(xy 1.130847 -1.204911)
(xy 1.137625 -1.211664)
(xy 1.144282 -1.214992)
(xy 1.151009 -1.22172)
(xy 1.157717 -1.225061)
(xy 1.174467 -1.241836)
(xy 1.18121 -1.245195)
(xy 1.1977 -1.261685)
(xy 1.1977 -1.264927)
(xy 1.215629 -1.28299)
(xy 1.221175 -1.288535)
(xy 1.221175 -1.291886)
(xy 1.260514 -1.331225)
(xy 1.303838 -1.331225)
(xy 1.579425 -1.136032)
(xy 1.579425 -1.095061)
(xy 1.567181 -1.070481)
(xy 1.566 -1.069303)
(xy 1.566 -1.066017)
(xy 1.5526 -1.052592)
(xy 1.5526 -1.049214)
(xy 1.529125 -1.02574)
(xy 1.529125 -1.022381)
(xy 1.465111 -0.958404)
(xy 1.458417 -0.955057)
(xy 1.438347 -0.934986)
(xy 1.431616 -0.931595)
(xy 1.421489 -0.921493)
(xy 1.41486 -0.918178)
(xy 1.408134 -0.911427)
(xy 1.401365 -0.908055)
(xy 1.398043 -0.904732)
(xy 1.391342 -0.901381)
(xy 1.38467 -0.894709)
(xy 1.377944 -0.891334)
(xy 1.374568 -0.887957)
(xy 1.361083 -0.881214)
(xy 1.357708 -0.877865)
(xy 1.351093 -0.874557)
(xy 1.347797 -0.871261)
(xy 1.333836 -0.864229)
(xy 1.320832 -0.857739)
(xy 1.317458 -0.85439)
(xy 1.303718 -0.84752)
(xy 1.303719 -0.84752)
(xy 1.296919 -0.844095)
(xy 1.290094 -0.840695)
(xy 1.290093 -0.840695)
(xy 1.280282 -0.83579)
(xy 1.270201 -0.832429)
(xy 1.266619 -0.830645)
(xy 1.266618 -0.830645)
(xy 1.260118 -0.827395)
(xy 1.260119 -0.827395)
(xy 1.250162 -0.82238)
(xy 1.240015 -0.819006)
(xy 1.233316 -0.815656)
(xy 1.219851 -0.811179)
(xy 1.219886 -0.811191)
(xy 1.213208 -0.808965)
(xy 1.206541 -0.805631)
(xy 1.193097 -0.801128)
(xy 1.181179 -0.797155)
(xy 1.167754 -0.793805)
(xy 1.157704 -0.790455)
(xy 1.128981 -0.783288)
(xy 1.129002 -0.783293)
(xy 1.115602 -0.779943)
(xy 1.101048 -0.776284)
(xy 1.082278 -0.772536)
(xy 1.040231 -0.765537)
(xy 1.011783 -0.761984)
(xy 0.97514 -0.758325)
(xy 0.819648 -0.758325)
(xy 0.776301 -0.761933)
(xy 0.74802 -0.765465)
(xy 0.723537 -0.768958)
(xy 0.702047 -0.772536)
(xy 0.684448 -0.77605)
(xy 0.667638 -0.779432)
(xy 0.649788 -0.783002)
(xy 0.619921 -0.790455)
(xy 0.60987 -0.793805)
(xy 0.596446 -0.797155)
(xy 0.584528 -0.801128)
(xy 0.57627 -0.803893)
(xy 0.562928 -0.807229)
(xy 0.547659 -0.812306)
(xy 0.54096 -0.815656)
(xy 0.534274 -0.817879)
(xy 0.534239 -0.817891)
(xy 0.520782 -0.822376)
(xy 0.514054 -0.825752)
(xy 0.504043 -0.82909)
(xy 0.497362 -0.83243)
(xy 0.487272 -0.835785)
(xy 0.467129 -0.845869)
(xy 0.457104 -0.849211)
(xy 0.433784 -0.860856)
(xy 0.413094 -0.871221)
(xy 0.409761 -0.874553)
(xy 0.403623 -0.877612)
(xy 0.382932 -0.887957)
(xy 0.379556 -0.891332)
(xy 0.366157 -0.898032)
(xy 0.362834 -0.901354)
(xy 0.356109 -0.904705)
(xy 0.352731 -0.908082)
(xy 0.345947 -0.911475)
(xy 0.342624 -0.914822)
(xy 0.335984 -0.91813)
(xy 0.332607 -0.921507)
(xy 0.325907 -0.924857)
(xy 0.322584 -0.92818)
(xy 0.315816 -0.931552)
(xy 0.30909 -0.938303)
(xy 0.302432 -0.941632)
(xy 0.29576 -0.948304)
(xy 0.289006 -0.951669)
(xy 0.278956 -0.961743)
(xy 0.272242 -0.965089)
(xy 0.255492 -0.981863)
(xy 0.248784 -0.985205)
(xy 0.16465 -1.069339)
(xy 0.16465 -1.07269)
(xy 0.144525 -1.092814)
(xy 0.144525 -1.096192)
(xy 0.131125 -1.109617)
(xy 0.131125 -1.112939)
(xy 0.12105 -1.123014)
(xy 0.12105 -1.126364)
(xy 0.111 -1.136414)
(xy 0.111 -1.139764)
(xy 0.104275 -1.146489)
(xy 0.104275 -1.149839)
(xy 0.097575 -1.156539)
(xy 0.097575 -1.159944)
(xy 0.090875 -1.166669)
(xy 0.090875 -1.16988)
(xy 0.08415 -1.176555)
(xy 0.08415 -1.180014)
(xy 0.0808 -1.183364)
(xy 0.0808 -1.186739)
(xy 0.0741 -1.193439)
(xy 0.0741 -1.196789)
(xy 0.07075 -1.200139)
(xy 0.07075 -1.203598)
(xy 0.0674 -1.206973)
(xy 0.0674 -1.210189)
(xy 0.060675 -1.216914)
(xy 0.060675 -1.220264)
(xy 0.057325 -1.223614)
(xy 0.057325 -1.226989)
(xy 0.053975 -1.230339)
(xy 0.053975 -1.233689)
(xy 0.050625 -1.237039)
(xy 0.050625 -1.240389)
(xy 0.047275 -1.243739)
(xy 0.047275 -1.247089)
(xy 0.0439 -1.250464)
(xy 0.0439 -1.253814)
(xy 0.04055 -1.257164)
(xy 0.04055 -1.260514)
(xy 0.0372 -1.263864)
(xy 0.0372 -1.267323)
(xy 0.03385 -1.270698)
(xy 0.03385 -1.273939)
(xy 0.0305 -1.277289)
(xy 0.0305 -1.283989)
(xy 0.02715 -1.287339)
(xy 0.02715 -1.290714)
(xy 0.0238 -1.294064)
(xy 0.0238 -1.297305)
(xy 0.020425 -1.300655)
(xy 0.020425 -1.307573)
(xy 0.017075 -1.310948)
(xy 0.017075 -1.314189)
(xy 0.013725 -1.317539)
(xy 0.013725 -1.324239)
(xy 0.010375 -1.327589)
(xy 0.010375 -1.334314)
(xy 0.007025 -1.337664)
(xy 0.007025 -1.344364)
(xy 0.003675 -1.347714)
(xy 0.003675 -1.351064)
(xy 0.0003 -1.354439)
(xy 0.0003 -1.361139)
(xy -0.00305 -1.364489)
(xy -0.00305 -1.374564)
(xy -0.0064 -1.377914)
(xy -0.0064 -1.384614)
(xy -0.00975 -1.387964)
(xy -0.00975 -1.394689)
(xy -0.0131 -1.398039)
(xy -0.0131 -1.408089)
(xy -0.01645 -1.411439)
(xy -0.01645 -1.421405)
(xy -0.019825 -1.424755)
(xy -0.019825 -1.435023)
(xy -0.023175 -1.438398)
(xy -0.023175 -1.448339)
(xy -0.026525 -1.451689)
(xy -0.026525 -1.465114)
(xy -0.029875 -1.468464)
(xy -0.029875 -1.481889)
(xy -0.033225 -1.485239)
(xy -0.033225 -1.502014)
(xy -0.036575 -1.505364)
(xy -0.036575 -1.52538)
(xy -0.03995 -1.52873)
(xy -0.03995 -1.552314)
(xy -0.0433 -1.555664)
(xy -0.0433 -1.589214)
(xy -0.04665 -1.592564)
(xy -0.04665 -1.791502)
(xy -0.0433 -1.794877)
(xy -0.0433 -1.831752)
(xy -0.03995 -1.835127)
(xy -0.03995 -1.85882)
(xy -0.036575 -1.86217)
(xy -0.036575 -1.882186)
(xy -0.033225 -1.885536)
(xy -0.033225 -1.902311)
(xy -0.029875 -1.905661)
(xy -0.029875 -1.919086)
(xy -0.026525 -1.922436)
(xy -0.026525 -1.935727)
(xy -0.023175 -1.939102)
(xy -0.023175 -1.952611)
(xy -0.019825 -1.955961)
(xy -0.019825 -1.966145)
(xy -0.01645 -1.969495)
(xy -0.01645 -1.979327)
(xy -0.0131 -1.982702)
(xy -0.0131 -1.989511)
(xy -0.00975 -1.992861)
(xy -0.00975 -2.002936)
(xy -0.0064 -2.006286)
(xy -0.0064 -2.012986)
(xy -0.00305 -2.016336)
(xy -0.00305 -2.023061)
(xy 0.0003 -2.026411)
(xy 0.0003 -2.03657)
(xy 0.003675 -2.03992)
(xy 0.003675 -2.043052)
(xy 0.007025 -2.046427)
(xy 0.007025 -2.053236)
(xy 0.010375 -2.056586)
(xy 0.010375 -2.063177)
(xy 0.013725 -2.066552)
(xy 0.013725 -2.073361)
(xy 0.017075 -2.076711)
(xy 0.017075 -2.080061)
(xy 0.020425 -2.083411)
(xy 0.020425 -2.090245)
(xy 0.0238 -2.093595)
(xy 0.0238 -2.096836)
(xy 0.02715 -2.100186)
(xy 0.02715 -2.106911)
(xy 0.0305 -2.110261)
(xy 0.0305 -2.116961)
(xy 0.0372 -2.123661)
(xy 0.0372 -2.126902)
(xy 0.04055 -2.130277)
(xy 0.04055 -2.133736)
(xy 0.0439 -2.137086)
(xy 0.0439 -2.143895)
(xy 0.047275 -2.147245)
(xy 0.047275 -2.150511)
(xy 0.050625 -2.153861)
(xy 0.050625 -2.157211)
(xy 0.053975 -2.160561)
(xy 0.053975 -2.163911)
(xy 0.060675 -2.170611)
(xy 0.060675 -2.173986)
(xy 0.064025 -2.177336)
(xy 0.064025 -2.180795)
(xy 0.0674 -2.184145)
(xy 0.0674 -2.187277)
(xy 0.07075 -2.190652)
(xy 0.07075 -2.194111)
(xy 0.07745 -2.200811)
(xy 0.07745 -2.204161)
(xy 0.0808 -2.207511)
(xy 0.0808 -2.210752)
(xy 0.087525 -2.217527)
(xy 0.087525 -2.220936)
(xy 0.090875 -2.224286)
(xy 0.090875 -2.227581)
(xy 0.097575 -2.234306)
(xy 0.097575 -2.237711)
(xy 0.104275 -2.244411)
(xy 0.104275 -2.247761)
(xy 0.111 -2.254486)
(xy 0.111 -2.257836)
(xy 0.12105 -2.267886)
(xy 0.12105 -2.271236)
(xy 0.131125 -2.281311)
(xy 0.131125 -2.284661)
(xy 0.141175 -2.294711)
(xy 0.141175 -2.298086)
(xy 0.15795 -2.31486)
(xy 0.15795 -2.318211)
(xy 0.188125 -2.348385)
(xy 0.188125 -2.351736)
(xy 0.228659 -2.39227)
(xy 0.235343 -2.395599)
(xy 0.236287 -2.396547)
(xy 0.265532 -2.425793)
(xy 0.272271 -2.429162)
(xy 0.285629 -2.442553)
(xy 0.292399 -2.445938)
(xy 0.299125 -2.452639)
(xy 0.305739 -2.455946)
(xy 0.312466 -2.462698)
(xy 0.319234 -2.466069)
(xy 0.322557 -2.469393)
(xy 0.329257 -2.472743)
(xy 0.335984 -2.47947)
(xy 0.342624 -2.482777)
(xy 0.345947 -2.486125)
(xy 0.35275 -2.489526)
(xy 0.371769 -2.508475)
(xy 0.383957 -2.508475)
(xy 0.38628 -2.509641)
(xy 0.389632 -2.512993)
(xy 0.403623 -2.519988)
(xy 0.410381 -2.523355)
(xy 0.410381 -2.523354)
(xy 0.416881 -2.526604)
(xy 0.416881 -2.526605)
(xy 0.423681 -2.53003)
(xy 0.430506 -2.53343)
(xy 0.430506 -2.533429)
(xy 0.443873 -2.540113)
(xy 0.450631 -2.54348)
(xy 0.450631 -2.543479)
(xy 0.457131 -2.546729)
(xy 0.457131 -2.54673)
(xy 0.463931 -2.550155)
(xy 0.470756 -2.553555)
(xy 0.470756 -2.553554)
(xy 0.480568 -2.55846)
(xy 0.490648 -2.56182)
(xy 0.494231 -2.563605)
(xy 0.494231 -2.563604)
(xy 0.504043 -2.56851)
(xy 0.514054 -2.571847)
(xy 0.520782 -2.575224)
(xy 0.534239 -2.579709)
(xy 0.534274 -2.579721)
(xy 0.544349 -2.583071)
(xy 0.544314 -2.583059)
(xy 0.554364 -2.586409)
(xy 0.554399 -2.586421)
(xy 0.564474 -2.589771)
(xy 0.564439 -2.589759)
(xy 0.574418 -2.593085)
(xy 0.574418 -2.593086)
(xy 0.584528 -2.596472)
(xy 0.596446 -2.600445)
(xy 0.611744 -2.604262)
(xy 0.611723 -2.604257)
(xy 0.623279 -2.607146)
(xy 0.634492 -2.610874)
(xy 0.653089 -2.614588)
(xy 0.666491 -2.617964)
(xy 0.702047 -2.625064)
(xy 0.723537 -2.628642)
(xy 0.74802 -2.632135)
(xy 0.776286 -2.635665)
(xy 0.819632 -2.6393)
(xy 0.975159 -2.6393)
)
(stroke (width 0) (type default)) (fill solid) (layer "F.Cu") (tstamp b249901f-c2e9-4c38-852a-e2816130e93a))
)
(gr_rect (start 70 85) (end 74 89)
(stroke (width 0.1) (type default)) (fill none) (layer "Edge.Cuts") (tstamp 9d07ce53-5f7e-43a1-b557-4bcf5c8818ba))
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,537 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.5,
"copper_text_size_v": 1.5,
"copper_text_thickness": 0.3,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 2,
"dimension_units": 2,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": true,
"text_position": 1,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.09999999999999999,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 0.0,
"height": 0.621,
"width": 0.95
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.16
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
},
{
"gap": 0.15,
"via_gap": 0.2,
"width": 0.2
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "error",
"copper_edge_clearance": "error",
"copper_sliver": "error",
"courtyards_overlap": "warning",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "warning",
"extra_footprint": "warning",
"footprint": "error",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"isolated_copper": "warning",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "warning",
"lib_footprint_mismatch": "ignore",
"malformed_courtyard": "ignore",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "ignore",
"silk_over_copper": "ignore",
"silk_overlap": "ignore",
"skew_out_of_range": "error",
"solder_mask_bridge": "ignore",
"starved_thermal": "error",
"text_height": "ignore",
"text_thickness": "ignore",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "error",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "ignore",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.16,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.39999999999999997,
"min_hole_clearance": 0.254,
"min_hole_to_hole": 0.5,
"min_microvia_diameter": 0.39999999999999997,
"min_microvia_drill": 0.19999999999999998,
"min_resolved_spokes": 1,
"min_silk_clearance": 0.0,
"min_text_height": 0.6,
"min_text_thickness": 0.15,
"min_through_hole_diameter": 0.19999999999999998,
"min_track_width": 0.16,
"min_via_annular_width": 0.16,
"min_via_diameter": 0.39999999999999997,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 5,
"td_on_pad_in_zone": false,
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": true,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_curve_segcount": 5,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 0.5,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_curve_segcount": 5,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 0.5,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_curve_segcount": 5,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 0.5,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [
0.0,
0.2,
0.3,
0.4,
0.5,
0.6,
0.7,
0.8,
0.9,
1.0,
1.2,
1.5,
2.0,
2.5,
3.0,
4.0,
5.0
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
},
{
"diameter": 0.6,
"drill": 0.2
},
{
"diameter": 0.9,
"drill": 0.5
}
],
"zones_allow_external_fillets": false
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "warning",
"missing_bidi_pin": "warning",
"missing_input_pin": "warning",
"missing_power_pin": "error",
"missing_unit": "warning",
"multiple_net_names": "warning",
"net_not_bus_member": "warning",
"no_connect_connected": "warning",
"no_connect_dangling": "warning",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "error",
"power_pin_not_driven": "error",
"similar_labels": "warning",
"simulation_model_issue": "ignore",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "W220921.01.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.15,
"diff_pair_gap": 0.15,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.6,
"microvia_drill": 0.2,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.2,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "Assembly/Export STEP/W220921.01.step",
"vrml": ""
},
"page_layout_descr_file": "worksheets/A5_WiSER.kicad_wks"
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 40.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "worksheets\\A4_WiSER.kicad_wks",
"plot_directory": "Documentation/",
"spice_adjust_passive_values": false,
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"3648648f-5acc-4713-a8ab-e21fc1644e2e",
""
]
],
"text_variables": {
"ProjectAuthor": "René Široký",
"ProjectDate": "21. 9. 2022",
"ProjectNumber": "W220921.01",
"ProjectTitle": "TMDSEMU110-U Debug Probe SWD Adapter",
"ProjectVariant": "Default"
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,591 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"board_outline_line_width": 0.09999999999999999,
"copper_line_width": 0.19999999999999998,
"copper_text_italic": false,
"copper_text_size_h": 1.0,
"copper_text_size_v": 1.0,
"copper_text_thickness": 0.15,
"copper_text_upright": false,
"courtyard_line_width": 0.049999999999999996,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": false,
"text_position": 0,
"units_format": 1
},
"fab_line_width": 0.09999999999999999,
"fab_text_italic": false,
"fab_text_size_h": 1.0,
"fab_text_size_v": 1.0,
"fab_text_thickness": 0.15,
"fab_text_upright": false,
"other_line_width": 0.15,
"other_text_italic": false,
"other_text_size_h": 1.0,
"other_text_size_v": 1.0,
"other_text_thickness": 0.15,
"other_text_upright": false,
"pads": {
"drill": 2.0,
"height": 2.0,
"width": 2.0
},
"silk_line_width": 0.15,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.15,
"silk_text_upright": false,
"zones": {
"45_degree_only": false,
"min_clearance": 0.19999999999999998
}
},
"diff_pair_dimensions": [
{
"gap": 0.0,
"via_gap": 0.0,
"width": 0.0
}
],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "ignore",
"connection_width": "error",
"copper_edge_clearance": "error",
"copper_sliver": "error",
"courtyards_overlap": "error",
"diff_pair_gap_out_of_range": "error",
"diff_pair_uncoupled_length_too_long": "error",
"drill_out_of_range": "error",
"duplicate_footprints": "error",
"extra_footprint": "error",
"footprint": "error",
"footprint_type_mismatch": "error",
"hole_clearance": "error",
"hole_near_hole": "error",
"invalid_outline": "error",
"isolated_copper": "error",
"item_on_disabled_layer": "error",
"items_not_allowed": "error",
"length_out_of_range": "error",
"lib_footprint_issues": "ignore",
"lib_footprint_mismatch": "ignore",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"missing_courtyard": "error",
"missing_footprint": "error",
"net_conflict": "error",
"npth_inside_courtyard": "error",
"padstack": "error",
"pth_inside_courtyard": "error",
"shorting_items": "error",
"silk_edge_clearance": "error",
"silk_over_copper": "error",
"silk_overlap": "error",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "error",
"text_thickness": "error",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_dangling": "error",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "error",
"zones_intersect": "error"
},
"rules": {
"allow_blind_buried_vias": false,
"allow_microvias": false,
"max_error": 0.005,
"min_clearance": 0.19999999999999998,
"min_connection": 0.19999999999999998,
"min_copper_edge_clearance": 0.19999999999999998,
"min_hole_clearance": 0.19999999999999998,
"min_hole_to_hole": 0.19999999999999998,
"min_microvia_diameter": 0.19999999999999998,
"min_microvia_drill": 0.09999999999999999,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.7999999999999999,
"min_text_thickness": 0.12,
"min_through_hole_diameter": 0.19999999999999998,
"min_track_width": 0.19999999999999998,
"min_via_annular_width": 0.09999999999999999,
"min_via_diameter": 0.39999999999999997,
"solder_mask_clearance": 0.0,
"solder_mask_min_width": 0.0,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 5,
"td_on_pad_in_zone": false,
"td_onpadsmd": true,
"td_onroundshapesonly": false,
"td_ontrackend": false,
"td_onviapad": true
}
],
"teardrop_parameters": [
{
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [
0.0,
0.2,
0.3,
0.5,
0.8,
2.0
],
"via_dimensions": [
{
"diameter": 0.0,
"drill": 0.0
},
{
"diameter": 0.4,
"drill": 0.2
}
],
"zones_allow_external_fillets": true,
"zones_use_no_outline": true
},
"layer_presets": [],
"viewports": []
},
"boards": [],
"cvpcb": {
"equivalence_files": []
},
"erc": {
"erc_exclusions": [],
"meta": {
"version": 0
},
"pin_map": [
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
1,
0,
1,
2
],
[
0,
1,
0,
0,
0,
0,
1,
1,
2,
1,
1,
2
],
[
0,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
0,
2
],
[
1,
1,
1,
1,
1,
0,
1,
1,
1,
1,
1,
2
],
[
0,
0,
0,
1,
0,
0,
1,
0,
0,
0,
0,
2
],
[
0,
2,
1,
2,
0,
0,
1,
0,
2,
2,
2,
2
],
[
0,
2,
0,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
0,
2,
1,
1,
0,
0,
1,
0,
2,
0,
0,
2
],
[
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2,
2
]
],
"rule_severities": {
"bus_definition_conflict": "error",
"bus_entry_needed": "error",
"bus_to_bus_conflict": "error",
"bus_to_net_conflict": "error",
"conflicting_netclasses": "error",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "error",
"extra_units": "error",
"global_label_dangling": "error",
"hier_label_mismatch": "error",
"label_dangling": "error",
"lib_symbol_issues": "error",
"missing_bidi_pin": "error",
"missing_input_pin": "error",
"missing_power_pin": "error",
"missing_unit": "error",
"multiple_net_names": "error",
"net_not_bus_member": "error",
"no_connect_connected": "error",
"no_connect_dangling": "error",
"pin_not_connected": "error",
"pin_not_driven": "error",
"pin_to_pin": "error",
"power_pin_not_driven": "error",
"similar_labels": "error",
"simulation_model_issue": "error",
"unannotated": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "pulse.kicad_pro",
"version": 1
},
"net_settings": {
"classes": [
{
"bus_width": 12,
"clearance": 0.2,
"diff_pair_gap": 0.25,
"diff_pair_via_gap": 0.25,
"diff_pair_width": 0.2,
"line_style": 0,
"microvia_diameter": 0.3,
"microvia_drill": 0.1,
"name": "Default",
"pcb_color": "rgba(0, 0, 0, 0.000)",
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.4,
"via_drill": 0.2,
"wire_width": 6
}
],
"meta": {
"version": 3
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"specctra_dsn": "",
"step": "",
"vrml": ""
},
"page_layout_descr_file": "${KICAD_USER_TEMPLATE_DIR}/V2_A4_Empty.kicad_wks"
},
"schematic": {
"annotate_start_num": 0,
"drawing": {
"dashed_lines_dash_length_ratio": 12.0,
"dashed_lines_gap_length_ratio": 3.0,
"default_line_thickness": 6.0,
"default_text_size": 50.0,
"field_names": [],
"intersheets_ref_own_page": false,
"intersheets_ref_prefix": "",
"intersheets_ref_short": false,
"intersheets_ref_show": false,
"intersheets_ref_suffix": "",
"junction_size_choice": 3,
"label_size_ratio": 0.375,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.1
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"ngspice": {
"fix_include_paths": true,
"fix_passive_vals": false,
"meta": {
"version": 0
},
"model_mode": 0,
"workbook_filename": ""
},
"page_layout_descr_file": "${KICAD_USER_TEMPLATE_DIR}/V2_A4.kicad_wks",
"plot_directory": "",
"spice_adjust_passive_values": false,
"spice_current_sheet_as_root": false,
"spice_external_command": "spice \"%I\"",
"spice_model_current_sheet_as_root": true,
"spice_save_all_currents": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"6c8448b4-b04d-47e1-934e-e40cbe27a7be",
""
],
[
"ecb8eef8-bb26-4217-a3d3-147bd9b06112",
"PWM Channel 1"
],
[
"c0032080-b223-4ef5-af6e-f10445519ca7",
"PWM Channel 2"
],
[
"72fc00ec-a037-43b2-8be3-f6274b0c3d34",
"PWM Channel 3"
],
[
"c5e21047-c711-42c5-833c-f87be56058f4",
"PWM Channel 4"
],
[
"a89ccf9d-6e1e-42ce-a365-b8a588b2a764",
"PWM Channel 5"
],
[
"2e65de88-75bc-4218-bada-fc991c11693d",
"PWM Channel 6"
],
[
"a178fee9-8654-4c6d-afdd-d0f611515c27",
"PWM Channel 7"
],
[
"c39b559a-eba7-416b-9b64-29e457c350f9",
"PWM Channel 8"
],
[
"f374a830-6190-4414-97f7-cd95a96fcb7b",
"PWM Channel 9"
],
[
"f929036c-a21a-4759-9a71-4bb346b616ac",
"PWM Channel 12"
],
[
"11be0dca-9aa7-44a3-a97c-59531fd35a86",
"PWM Channel 11"
],
[
"0c49b5ee-ddea-43ea-ab5a-6c52ceb8d790",
"PWM Channel 10"
],
[
"87daeacc-2e6b-4f3e-a4a8-59a3ffd747c2",
"PWM Channel 13"
],
[
"1b24bac2-35ae-4e4e-8bc5-d88b5d418adf",
"PWM Channel 16"
],
[
"02d7dc07-d88b-46a9-8c27-5f474f94bba5",
"PWM Channel 15"
],
[
"ef3f4e24-65f6-49ab-9666-2948510217b4",
"PWM Channel 14"
],
[
"ba748654-beb9-4861-aa35-c19e08caaf2e",
"Power +24V"
],
[
"c6db2f80-f80f-4104-8ca1-02f0ab85cfea",
"Link Plug"
],
[
"2a03ea79-269e-4abf-833c-000ba0ff13d7",
"Link Socket"
]
],
"text_variables": {
"Order-Number": "JLCJLCJLCJLC"
}
}

View File

@ -0,0 +1,115 @@
(kicad_pcb (version 20230410) (generator pcbnew)
(general
(thickness 1.6)
)
(paper "A4")
(layers
(0 "F.Cu" signal)
(31 "B.Cu" signal)
(32 "B.Adhes" user "B.Adhesive")
(33 "F.Adhes" user "F.Adhesive")
(34 "B.Paste" user)
(35 "F.Paste" user)
(36 "B.SilkS" user "B.Silkscreen")
(37 "F.SilkS" user "F.Silkscreen")
(38 "B.Mask" user)
(39 "F.Mask" user)
(40 "Dwgs.User" user "User.Drawings")
(41 "Cmts.User" user "User.Comments")
(42 "Eco1.User" user "User.Eco1")
(43 "Eco2.User" user "User.Eco2")
(44 "Edge.Cuts" user)
(45 "Margin" user)
(46 "B.CrtYd" user "B.Courtyard")
(47 "F.CrtYd" user "F.Courtyard")
(48 "B.Fab" user)
(49 "F.Fab" user)
(50 "User.1" user)
(51 "User.2" user)
(52 "User.3" user)
(53 "User.4" user)
(54 "User.5" user)
(55 "User.6" user)
(56 "User.7" user)
(57 "User.8" user)
(58 "User.9" user)
)
(setup
(pad_to_mask_clearance 0)
(pcbplotparams
(layerselection 0x00010fc_ffffffff)
(plot_on_all_layers_selection 0x0000000_00000000)
(disableapertmacros false)
(usegerberextensions false)
(usegerberattributes true)
(usegerberadvancedattributes true)
(creategerberjobfile true)
(dashed_line_dash_ratio 12.000000)
(dashed_line_gap_ratio 3.000000)
(svgprecision 4)
(plotframeref false)
(viasonmask false)
(mode 1)
(useauxorigin false)
(hpglpennumber 1)
(hpglpenspeed 20)
(hpglpendiameter 15.000000)
(dxfpolygonmode true)
(dxfimperialunits true)
(dxfusepcbnewfont true)
(psnegative false)
(psa4output false)
(plotreference true)
(plotvalue true)
(plotinvisibletext false)
(sketchpadsonfab false)
(subtractmaskfromsilk false)
(outputformat 1)
(mirror false)
(drillshape 1)
(scaleselection 1)
(outputdirectory "")
)
)
(net 0 "")
(gr_poly
(pts
(xy 101.9556 69.1388)
(xy 133.096 69.2404)
(xy 133.2484 71.1708)
(xy 102.0572 71.1708)
(xy 102.0572 70.2564)
(xy 132.4356 70.2056)
(xy 102.0064 70.0024)
)
(stroke (width 0) (type solid)) (fill solid) (layer "F.Cu") (tstamp 53555c8c-8370-4dd2-82cd-fb5fcf7d0670))
(gr_poly
(pts
(xy 102.2096 76.5556)
(xy 133.4008 76.6064)
(xy 133.4008 74.3204)
(xy 102.2096 74.0664)
(xy 102.2096 75.184)
(xy 132.1308 75.438)
(xy 102.2096 75.7936)
)
(stroke (width 0) (type solid)) (fill solid) (layer "F.Cu") (tstamp 9e84cf11-135c-4d2a-a849-6dc335827c5c))
(gr_poly
(pts
(xy 102.2096 72.7964)
(xy 133.0452 73.152)
(xy 102.2096 73.2028)
(xy 101.9048 73.1012)
(xy 101.9048 72.898)
(xy 102.0572 72.7964)
)
(stroke (width 0) (type solid)) (fill solid) (layer "F.Cu") (tstamp ceafb5a5-949b-47d2-af13-6d5cb962e056))
(gr_rect (start 99.06 67.7164) (end 136.144 77.1652)
(stroke (width 0.1) (type default)) (fill none) (layer "Edge.Cuts") (tstamp 2be69152-e65e-49cc-b325-c520ff486dc0))
)

View File

@ -47,6 +47,7 @@ set( QA_PCBNEW_SRCS
drc/test_drc_courtyard_overlap.cpp
drc/test_drc_regressions.cpp
drc/test_drc_copper_conn.cpp
drc/test_drc_copper_sliver.cpp
drc/test_solder_mask_bridging.cpp
plugins/altium/test_altium_rule_transformer.cpp

View File

@ -0,0 +1,106 @@
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2023 KiCad Developers, see AUTHORS.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <qa_utils/wx_utils/unit_test_utils.h>
#include <pcbnew_utils/board_test_utils.h>
#include <board.h>
#include <board_design_settings.h>
#include <pad.h>
#include <pcb_track.h>
#include <pcb_marker.h>
#include <footprint.h>
#include <drc/drc_item.h>
#include <settings/settings_manager.h>
struct DRC_REGRESSION_TEST_FIXTURE
{
DRC_REGRESSION_TEST_FIXTURE() :
m_settingsManager( true /* headless */ )
{ }
SETTINGS_MANAGER m_settingsManager;
std::unique_ptr<BOARD> m_board;
};
BOOST_FIXTURE_TEST_CASE( DRCCopperSliver, DRC_REGRESSION_TEST_FIXTURE )
{
// Check for minimum copper connection errors
std::vector<std::pair<wxString, int>> tests =
{
{ "sliver", 1 },
{ "issue14449", 0 },
{ "issue14549", 0 },
{ "issue14549_2", 0 },
{ "issue14559", 0 }
};
for( const std::pair<wxString, int>& test : tests )
{
KI_TEST::LoadBoard( m_settingsManager, test.first, m_board );
KI_TEST::FillZones( m_board.get() );
std::vector<DRC_ITEM> violations;
BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings();
// Disable DRC tests not useful or not handled in this testcase
for( int ii = DRCE_FIRST; ii <= DRCE_LAST; ++ii )
bds.m_DRCSeverities[ ii ] = SEVERITY::RPT_SEVERITY_IGNORE;
// Ensure that our desired error is fired
bds.m_DRCSeverities[ DRCE_COPPER_SLIVER ] = SEVERITY::RPT_SEVERITY_ERROR;
bds.m_DRCEngine->SetViolationHandler(
[&]( const std::shared_ptr<DRC_ITEM>& aItem, VECTOR2I aPos, int aLayer )
{
if( bds.GetSeverity( aItem->GetErrorCode() ) == SEVERITY::RPT_SEVERITY_ERROR )
violations.push_back( *aItem );
} );
bds.m_DRCEngine->RunTests( EDA_UNITS::MILLIMETRES, true, false );
if( violations.size() == test.second )
{
BOOST_CHECK_EQUAL( 1, 1 ); // quiet "did not check any assertions" warning
BOOST_TEST_MESSAGE( wxString::Format( "DRC copper sliver: %s, passed", test.first ) );
}
else
{
UNITS_PROVIDER unitsProvider( pcbIUScale, EDA_UNITS::INCHES );
std::map<KIID, EDA_ITEM*> itemMap;
m_board->FillItemMap( itemMap );
for( const DRC_ITEM& item : violations )
{
BOOST_TEST_MESSAGE( item.ShowReport( &unitsProvider, RPT_SEVERITY_ERROR,
itemMap ) );
}
BOOST_ERROR( wxString::Format( "DRC copper sliver: %s, failed (violations found %d expected %d)",
test.first, (int)violations.size(), test.second ) );
}
}
}

View File

@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 22 March 2023 *
* Date : 8 April 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : Core Clipper Library structures and functions *
@ -50,7 +50,9 @@ namespace Clipper2Lib
const int non_pair_error_i = 4; // non-fatal
const int range_error_i = 64;
#ifndef PI
static const double PI = 3.141592653589793238;
#endif
static const int64_t MAX_COORD = INT64_MAX >> 2;
static const int64_t MIN_COORD = -MAX_COORD;
static const int64_t INVALID = INT64_MAX;
@ -558,38 +560,22 @@ namespace Clipper2Lib
}
template<typename T>
inline Path<T> StripDuplicates(const Path<T>& path, bool is_closed_path)
inline void StripDuplicates( Path<T>& path, bool is_closed_path)
{
if (path.size() == 0) return Path<T>();
Path<T> result;
result.reserve(path.size());
typename Path<T>::const_iterator path_iter = path.cbegin();
Point<T> first_pt = *path_iter++, last_pt = first_pt;
result.push_back(first_pt);
for (; path_iter != path.cend(); ++path_iter)
{
if (*path_iter != last_pt)
{
last_pt = *path_iter;
result.push_back(last_pt);
}
}
if (!is_closed_path) return result;
while (result.size() > 1 && result.back() == first_pt) result.pop_back();
return result;
//https://stackoverflow.com/questions/1041620/whats-the-most-efficient-way-to-erase-duplicates-and-sort-a-vector#:~:text=Let%27s%20compare%20three%20approaches%3A
path.erase(std::unique(path.begin(), path.end()),path.end());
if (is_closed_path)
while (path.size() > 1 && path.back() == path.front()) path.pop_back();
}
template<typename T>
inline Paths<T> StripDuplicates(const Paths<T>& paths, bool is_closed_path)
inline void StripDuplicates( Paths<T>& paths, bool is_closed_path)
{
Paths<T> result;
result.reserve(paths.size());
for (typename Paths<T>::const_iterator paths_citer = paths.cbegin();
paths_citer != paths.cend(); ++paths_citer)
for (typename Paths<T>::iterator paths_citer = paths.begin();
paths_citer != paths.end(); ++paths_citer)
{
result.push_back(StripDuplicates(*paths_citer, is_closed_path));
StripDuplicates(*paths_citer, is_closed_path);
}
return result;
}
// Miscellaneous ------------------------------------------------------------

View File

@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 2 March 2023 *
* Date : 22 April 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : This is the main polygon clipping module *
@ -10,7 +10,7 @@
#ifndef CLIPPER_ENGINE_H
#define CLIPPER_ENGINE_H
constexpr auto CLIPPER2_VERSION = "1.2.1";
constexpr auto CLIPPER2_VERSION = "1.2.2";
#include <cstdlib>
#include <iostream>
@ -260,8 +260,8 @@ namespace Clipper2Lib {
bool ExecuteInternal(ClipType ct, FillRule ft, bool use_polytrees);
void CleanCollinear(OutRec* outrec);
bool CheckBounds(OutRec* outrec);
bool CheckSplitOwner(OutRec* outrec);
void RecursiveCheckOwners(OutRec* outrec, PolyPath* polypath);
void DeepCheckOwners(OutRec* outrec, PolyPath* polypath);
#ifdef USINGZ
ZCallback64 zCallback_ = nullptr;
void SetZ(const Active& e1, const Active& e2, Point64& pt);

View File

@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 22 March 2023 *
* Date : 23 March 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : This module exports the Clipper2 Library (ie DLL/so) *
@ -157,14 +157,14 @@ EXTERN_DLL_EXPORT CPathsD InflatePathsD(const CPathsD paths,
int precision = 2, double miter_limit = 2.0,
double arc_tolerance = 0.0, bool reverse_solution = false);
// RectClip & RectClipLines:
EXTERN_DLL_EXPORT CPaths64 RectClip64(const CRect64& rect,
// ExecuteRectClip & ExecuteRectClipLines:
EXTERN_DLL_EXPORT CPaths64 ExecuteRectClip64(const CRect64& rect,
const CPaths64 paths, bool convex_only = false);
EXTERN_DLL_EXPORT CPathsD RectClipD(const CRectD& rect,
EXTERN_DLL_EXPORT CPathsD ExecuteRectClipD(const CRectD& rect,
const CPathsD paths, int precision = 2, bool convex_only = false);
EXTERN_DLL_EXPORT CPaths64 RectClipLines64(const CRect64& rect,
EXTERN_DLL_EXPORT CPaths64 ExecuteRectClipLines64(const CRect64& rect,
const CPaths64 paths);
EXTERN_DLL_EXPORT CPathsD RectClipLinesD(const CRectD& rect,
EXTERN_DLL_EXPORT CPathsD ExecuteRectClipLinesD(const CRectD& rect,
const CPathsD paths, int precision = 2);
//////////////////////////////////////////////////////
@ -381,7 +381,7 @@ EXTERN_DLL_EXPORT CPathsD InflatePathsD(const CPathsD paths,
return CreateCPathsD(result, 1/scale);
}
EXTERN_DLL_EXPORT CPaths64 RectClip64(const CRect64& rect,
EXTERN_DLL_EXPORT CPaths64 ExecuteRectClip64(const CRect64& rect,
const CPaths64 paths, bool convex_only)
{
if (CRectIsEmpty(rect) || !paths) return nullptr;
@ -392,7 +392,7 @@ EXTERN_DLL_EXPORT CPaths64 RectClip64(const CRect64& rect,
return CreateCPaths64(result);
}
EXTERN_DLL_EXPORT CPathsD RectClipD(const CRectD& rect,
EXTERN_DLL_EXPORT CPathsD ExecuteRectClipD(const CRectD& rect,
const CPathsD paths, int precision, bool convex_only)
{
if (CRectIsEmpty(rect) || !paths) return nullptr;
@ -407,7 +407,7 @@ EXTERN_DLL_EXPORT CPathsD RectClipD(const CRectD& rect,
return CreateCPathsD(result, 1/scale);
}
EXTERN_DLL_EXPORT CPaths64 RectClipLines64(const CRect64& rect,
EXTERN_DLL_EXPORT CPaths64 ExecuteRectClipLines64(const CRect64& rect,
const CPaths64 paths)
{
if (CRectIsEmpty(rect) || !paths) return nullptr;
@ -418,7 +418,7 @@ EXTERN_DLL_EXPORT CPaths64 RectClipLines64(const CRect64& rect,
return CreateCPaths64(result);
}
EXTERN_DLL_EXPORT CPathsD RectClipLinesD(const CRectD& rect,
EXTERN_DLL_EXPORT CPathsD ExecuteRectClipLinesD(const CRectD& rect,
const CPathsD paths, int precision)
{
if (CRectIsEmpty(rect) || !paths) return nullptr;

View File

@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 9 February 2023 *
* Date : 21 April 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : This module provides a simple interface to the Clipper Library *
@ -24,7 +24,7 @@ namespace Clipper2Lib {
inline Paths64 BooleanOp(ClipType cliptype, FillRule fillrule,
const Paths64& subjects, const Paths64& clips)
{
{
Paths64 result;
Clipper64 clipper;
clipper.AddSubject(subjects);
@ -58,7 +58,7 @@ namespace Clipper2Lib {
}
inline void BooleanOp(ClipType cliptype, FillRule fillrule,
const PathsD& subjects, const PathsD& clips,
const PathsD& subjects, const PathsD& clips,
PolyTreeD& polytree, int precision = 2)
{
polytree.Clear();
@ -75,7 +75,7 @@ namespace Clipper2Lib {
{
return BooleanOp(ClipType::Intersection, fillrule, subjects, clips);
}
inline PathsD Intersect(const PathsD& subjects, const PathsD& clips, FillRule fillrule, int decimal_prec = 2)
{
return BooleanOp(ClipType::Intersection, fillrule, subjects, clips, decimal_prec);
@ -145,7 +145,7 @@ namespace Clipper2Lib {
}
inline PathsD InflatePaths(const PathsD& paths, double delta,
JoinType jt, EndType et, double miter_limit = 2.0,
JoinType jt, EndType et, double miter_limit = 2.0,
int precision = 2, double arc_tolerance = 0.0)
{
int error_code = 0;
@ -197,24 +197,24 @@ namespace Clipper2Lib {
return result;
}
inline Paths64 ExecuteRectClip(const Rect64& rect,
const Paths64& paths, bool convex_only = false)
inline Paths64 ExecuteRectClip(const Rect64& rect,
const Paths64& paths, bool convex_only)
{
if (rect.IsEmpty() || paths.empty()) return Paths64();
class RectClip rc(rect);
RectClip rc(rect);
return rc.Execute(paths, convex_only);
}
inline Paths64 ExecuteRectClip(const Rect64& rect,
const Path64& path, bool convex_only = false)
const Path64& path, bool convex_only)
{
if (rect.IsEmpty() || path.empty()) return Paths64();
class RectClip rc(rect);
RectClip rc(rect);
return rc.Execute(Paths64{ path }, convex_only);
}
inline PathsD ExecuteRectClip(const RectD& rect,
const PathsD& paths, bool convex_only = false, int precision = 2)
const PathsD& paths, bool convex_only, int precision = 2)
{
if (rect.IsEmpty() || paths.empty()) return PathsD();
int error_code = 0;
@ -222,15 +222,15 @@ namespace Clipper2Lib {
if (error_code) return PathsD();
const double scale = std::pow(10, precision);
Rect64 r = ScaleRect<int64_t, double>(rect, scale);
class RectClip rc(r);
RectClip rc(r);
Paths64 pp = ScalePaths<int64_t, double>(paths, scale, error_code);
if (error_code) return PathsD(); // ie: error_code result is lost
if (error_code) return PathsD(); // ie: error_code result is lost
return ScalePaths<double, int64_t>(
rc.Execute(pp, convex_only), 1 / scale, error_code);
}
inline PathsD ExecuteRectClip(const RectD& rect,
const PathD& path, bool convex_only = false, int precision = 2)
const PathD& path, bool convex_only, int precision = 2)
{
return ExecuteRectClip(rect, PathsD{ path }, convex_only, precision);
}
@ -238,7 +238,7 @@ namespace Clipper2Lib {
inline Paths64 ExecuteRectClipLines(const Rect64& rect, const Paths64& lines)
{
if (rect.IsEmpty() || lines.empty()) return Paths64();
class RectClipLines rcl(rect);
RectClipLines rcl(rect);
return rcl.Execute(lines);
}
@ -247,11 +247,6 @@ namespace Clipper2Lib {
return ExecuteRectClipLines(rect, Paths64{ line });
}
inline PathsD ExecuteRectClipLines(const RectD& rect, const PathD& line, int precision = 2)
{
return ExecuteRectClip(rect, PathsD{ line }, precision);
}
inline PathsD ExecuteRectClipLines(const RectD& rect, const PathsD& lines, int precision = 2)
{
if (rect.IsEmpty() || lines.empty()) return PathsD();
@ -260,13 +255,18 @@ namespace Clipper2Lib {
if (error_code) return PathsD();
const double scale = std::pow(10, precision);
Rect64 r = ScaleRect<int64_t, double>(rect, scale);
class RectClipLines rcl(r);
RectClipLines rcl(r);
Paths64 p = ScalePaths<int64_t, double>(lines, scale, error_code);
if (error_code) return PathsD();
p = rcl.Execute(p);
return ScalePaths<double, int64_t>(p, 1 / scale, error_code);
}
inline PathsD ExecuteRectClipLines(const RectD& rect, const PathD& line, int precision = 2)
{
return ExecuteRectClipLines(rect, PathsD{ line }, precision);
}
namespace details
{
@ -316,7 +316,7 @@ namespace Clipper2Lib {
return true;
}
static void OutlinePolyPath(std::ostream& os,
static void OutlinePolyPath(std::ostream& os,
bool isHole, size_t count, const std::string& preamble)
{
std::string plural = (count == 1) ? "." : "s.";
@ -366,10 +366,11 @@ namespace Clipper2Lib {
}
}
} // end details namespace
} // end details namespace
inline std::ostream& operator<< (std::ostream& os, const PolyTree64& pp)
{
os << std::endl << "Polytree root" << std::endl;
PolyPath64List::const_iterator it = pp.begin();
for (; it < pp.end() - 1; ++it)
details::OutlinePolyPath64(os, **it, " ", false);
@ -409,7 +410,7 @@ namespace Clipper2Lib {
inline bool CheckPolytreeFullyContainsChildren(const PolyTree64& polytree)
{
for (const auto& child : polytree)
if (child->Count() > 0 &&
if (child->Count() > 0 &&
!details::PolyPath64ContainsChildren(*child))
return false;
return true;
@ -574,12 +575,12 @@ namespace Clipper2Lib {
double cp = std::abs(CrossProduct(pt1, pt2, pt3));
return (cp * cp) / (DistanceSqr(pt1, pt2) * DistanceSqr(pt2, pt3)) < sin_sqrd_min_angle_rads;
}
template <typename T>
inline Path<T> Ellipse(const Rect<T>& rect, int steps = 0)
{
return Ellipse(rect.MidPoint(),
static_cast<double>(rect.Width()) *0.5,
return Ellipse(rect.MidPoint(),
static_cast<double>(rect.Width()) *0.5,
static_cast<double>(rect.Height()) * 0.5, steps);
}
@ -620,7 +621,7 @@ namespace Clipper2Lib {
return Sqr(a * d - c * b) / (c * c + d * d);
}
inline size_t GetNext(size_t current, size_t high,
inline size_t GetNext(size_t current, size_t high,
const std::vector<bool>& flags)
{
++current;
@ -631,7 +632,7 @@ namespace Clipper2Lib {
return current;
}
inline size_t GetPrior(size_t current, size_t high,
inline size_t GetPrior(size_t current, size_t high,
const std::vector<bool>& flags)
{
if (current == 0) current = high;
@ -644,8 +645,8 @@ namespace Clipper2Lib {
}
template <typename T>
inline Path<T> SimplifyPath(const Path<T> path,
double epsilon, bool isOpenPath = false)
inline Path<T> SimplifyPath(const Path<T> path,
double epsilon, bool isClosedPath = true)
{
const size_t len = path.size(), high = len -1;
const double epsSqr = Sqr(epsilon);
@ -654,16 +655,16 @@ namespace Clipper2Lib {
std::vector<bool> flags(len);
std::vector<double> distSqr(len);
size_t prior = high, curr = 0, start, next, prior2, next2;
if (isOpenPath)
{
distSqr[0] = MAX_DBL;
distSqr[high] = MAX_DBL;
}
else
if (isClosedPath)
{
distSqr[0] = PerpendicDistFromLineSqrd(path[0], path[high], path[1]);
distSqr[high] = PerpendicDistFromLineSqrd(path[high], path[0], path[high - 1]);
}
else
{
distSqr[0] = MAX_DBL;
distSqr[high] = MAX_DBL;
}
for (size_t i = 1; i < high; ++i)
distSqr[i] = PerpendicDistFromLineSqrd(path[i], path[i - 1], path[i + 1]);
@ -678,7 +679,7 @@ namespace Clipper2Lib {
} while (curr != start && distSqr[curr] > epsSqr);
if (curr == start) break;
}
prior = GetPrior(curr, high, flags);
next = GetNext(curr, high, flags);
if (next == prior) break;
@ -689,7 +690,7 @@ namespace Clipper2Lib {
next = GetNext(next, high, flags);
next2 = GetNext(next, high, flags);
distSqr[curr] = PerpendicDistFromLineSqrd(path[curr], path[prior], path[next]);
if (next != high || !isOpenPath)
if (next != high || isClosedPath)
distSqr[next] = PerpendicDistFromLineSqrd(path[next], path[curr], path[next2]);
curr = next;
}
@ -700,7 +701,7 @@ namespace Clipper2Lib {
next = GetNext(next, high, flags);
prior2 = GetPrior(prior, high, flags);
distSqr[curr] = PerpendicDistFromLineSqrd(path[curr], path[prior], path[next]);
if (prior != 0 || !isOpenPath)
if (prior != 0 || isClosedPath)
distSqr[prior] = PerpendicDistFromLineSqrd(path[prior], path[prior2], path[curr]);
}
}
@ -712,13 +713,13 @@ namespace Clipper2Lib {
}
template <typename T>
inline Paths<T> SimplifyPaths(const Paths<T> paths,
double epsilon, bool isOpenPath = false)
inline Paths<T> SimplifyPaths(const Paths<T> paths,
double epsilon, bool isClosedPath = true)
{
Paths<T> result;
result.reserve(paths.size());
for (const auto& path : paths)
result.push_back(SimplifyPath(path, epsilon, isOpenPath));
result.push_back(SimplifyPath(path, epsilon, isClosedPath));
return result;
}

View File

@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 19 March 2023 *
* Date : 23 April 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : This is the main polygon clipping module *
@ -594,6 +594,9 @@ namespace Clipper2Lib {
//for each path create a circular double linked list of vertices
Vertex* v0 = v, * curr_v = v, * prev_v = nullptr;
if (path.empty())
continue;
v->prev = nullptr;
int cnt = 0;
for (const Point64& pt : path)
@ -1533,7 +1536,7 @@ namespace Clipper2Lib {
InsertScanline(e->top.y);
CheckJoinLeft(*e, e->bot);
CheckJoinRight(*e, e->bot);
CheckJoinRight(*e, e->bot, true); // (#500)
}
Active* FindEdgeWithMatchingLocMin(Active* e)
@ -2124,7 +2127,11 @@ namespace Clipper2Lib {
else if (Path1InsidePath2(or1->pts, or2->pts))
SetOwner(or1, or2);
else
{
if (!or1->splits) or1->splits = new OutRecList();
or1->splits->push_back(or2); //(#498)
or2->owner = or1;
}
}
else
or2->owner = or1;
@ -2635,10 +2642,10 @@ namespace Clipper2Lib {
const Point64& pt, bool check_curr_x)
{
Active* prev = e.prev_in_ael;
if (IsOpen(e) || !IsHotEdge(e) || !prev ||
IsOpen(*prev) || !IsHotEdge(*prev) ||
pt.y < e.top.y + 2 || pt.y < prev->top.y + 2) // avoid trivial joins
return;
if (IsOpen(e) || !IsHotEdge(e) || !prev ||
IsOpen(*prev) || !IsHotEdge(*prev)) return;
if ((pt.y < e.top.y + 2 || pt.y < prev->top.y + 2) &&
((e.bot.y > pt.y) || (prev->bot.y > pt.y))) return; // avoid trivial joins
if (check_curr_x)
{
@ -2661,10 +2668,10 @@ namespace Clipper2Lib {
const Point64& pt, bool check_curr_x)
{
Active* next = e.next_in_ael;
if (IsOpen(e) || !IsHotEdge(e) ||
!next || IsOpen(*next) || !IsHotEdge(*next) ||
pt.y < e.top.y +2 || pt.y < next->top.y +2) // avoids trivial joins
return;
if (IsOpen(e) || !IsHotEdge(e) ||
!next || IsOpen(*next) || !IsHotEdge(*next)) return;
if ((pt.y < e.top.y +2 || pt.y < next->top.y +2) &&
((e.bot.y > pt.y) || (next->bot.y > pt.y))) return; // avoid trivial joins
if (check_curr_x)
{
@ -2679,6 +2686,7 @@ namespace Clipper2Lib {
JoinOutrecPaths(e, *next);
else
JoinOutrecPaths(*next, e);
e.join_with = JoinWith::Right;
next->join_with = JoinWith::Left;
}
@ -2755,6 +2763,23 @@ namespace Clipper2Lib {
return true;
}
bool ClipperBase::CheckSplitOwner(OutRec* outrec)
{
for (auto s : *outrec->owner->splits)
{
OutRec* split = GetRealOutRec(s);
if (split && split != outrec &&
split != outrec->owner && CheckBounds(split) &&
split->bounds.Contains(outrec->bounds) &&
Path1InsidePath2(outrec->pts, split->pts))
{
outrec->owner = split; //found in split
return true;
}
}
return false;
}
void ClipperBase::RecursiveCheckOwners(OutRec* outrec, PolyPath* polypath)
{
// pre-condition: outrec will have valid bounds
@ -2762,52 +2787,25 @@ namespace Clipper2Lib {
if (outrec->polypath || outrec->bounds.IsEmpty()) return;
while (outrec->owner &&
(!outrec->owner->pts || !CheckBounds(outrec->owner)))
outrec->owner = outrec->owner->owner;
if (outrec->owner && !outrec->owner->polypath)
RecursiveCheckOwners(outrec->owner, polypath);
while (outrec->owner)
if (outrec->owner->bounds.Contains(outrec->bounds) &&
Path1InsidePath2(outrec->pts, outrec->owner->pts))
break; // found - owner contain outrec!
else
outrec->owner = outrec->owner->owner;
{
if (outrec->owner->splits && CheckSplitOwner(outrec)) break;
if (outrec->owner->pts && CheckBounds(outrec->owner) &&
outrec->owner->bounds.Contains(outrec->bounds) &&
Path1InsidePath2(outrec->pts, outrec->owner->pts)) break;
outrec->owner = outrec->owner->owner;
}
if (outrec->owner)
{
if (!outrec->owner->polypath)
RecursiveCheckOwners(outrec->owner, polypath);
outrec->polypath = outrec->owner->polypath->AddChild(outrec->path);
}
else
outrec->polypath = polypath->AddChild(outrec->path);
}
void ClipperBase::DeepCheckOwners(OutRec* outrec, PolyPath* polypath)
{
RecursiveCheckOwners(outrec, polypath);
while (outrec->owner && outrec->owner->splits)
{
OutRec* split = nullptr;
for (auto s : *outrec->owner->splits)
{
split = GetRealOutRec(s);
if (split && split != outrec &&
split != outrec->owner && CheckBounds(split) &&
split->bounds.Contains(outrec->bounds) &&
Path1InsidePath2(outrec->pts, split->pts))
{
RecursiveCheckOwners(split, polypath);
outrec->owner = split; //found in split
break; // inner 'for' loop
}
else
split = nullptr;
}
if (!split) break;
}
}
void Clipper64::BuildPaths64(Paths64& solutionClosed, Paths64* solutionOpen)
{
solutionClosed.resize(0);
@ -2866,7 +2864,7 @@ namespace Clipper2Lib {
}
if (CheckBounds(outrec))
DeepCheckOwners(outrec, &polytree);
RecursiveCheckOwners(outrec, &polytree);
}
}
@ -2969,7 +2967,7 @@ namespace Clipper2Lib {
}
if (CheckBounds(outrec))
DeepCheckOwners(outrec, &polytree);
RecursiveCheckOwners(outrec, &polytree);
}
}

View File

@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 22 March 2023 *
* Date : 8 April 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : Path Offset (Inflate/Shrink) *
@ -302,13 +302,7 @@ void ClipperOffset::OffsetPoint(Group& group, Path64& path, size_t j, size_t& k)
if (sin_a > 1.0) sin_a = 1.0;
else if (sin_a < -1.0) sin_a = -1.0;
if (cos_a > 0.99) // almost straight - less than 8 degrees
{
group.path.push_back(GetPerpendic(path[j], norms[k], group_delta_));
if (cos_a < 0.9998) // greater than 1 degree (#424)
group.path.push_back(GetPerpendic(path[j], norms[j], group_delta_)); // (#418)
}
else if (cos_a > -0.99 && (sin_a * group_delta_ < 0))
if (cos_a > -0.99 && (sin_a * group_delta_ < 0))
{
// is concave
group.path.push_back(GetPerpendic(path[j], norms[k], group_delta_));
@ -316,21 +310,21 @@ void ClipperOffset::OffsetPoint(Group& group, Path64& path, size_t j, size_t& k)
// path reversals are fully cleaned with the trailing clipper
group.path.push_back(path[j]); // (#405)
group.path.push_back(GetPerpendic(path[j], norms[j], group_delta_));
}
else if (join_type_ == JoinType::Round)
DoRound(group, path, j, k, std::atan2(sin_a, cos_a));
}
else if (join_type_ == JoinType::Miter)
{
// miter unless the angle is so acute the miter would exceeds ML
if (cos_a > temp_lim_ - 1) DoMiter(group, path, j, k, cos_a);
else DoSquare(group, path, j, k);
}
// don't bother squaring angles that deviate < ~20 degrees because
// squaring will be indistinguishable from mitering and just be a lot slower
else if (cos_a > 0.9)
else if (cos_a > 0.9998)
// almost straight - less than 1 degree (#424)
DoMiter(group, path, j, k, cos_a);
else
else if (cos_a > 0.99 || join_type_ == JoinType::Square)
//angle less than 8 degrees or squared joins
DoSquare(group, path, j, k);
else
DoRound(group, path, j, k, std::atan2(sin_a, cos_a));
k = j;
}
@ -481,10 +475,11 @@ void ClipperOffset::DoGroupOffset(Group& group)
bool is_joined =
(end_type_ == EndType::Polygon) ||
(end_type_ == EndType::Joined);
Paths64::const_iterator path_iter;
for(path_iter = group.paths_in.cbegin(); path_iter != group.paths_in.cend(); ++path_iter)
Paths64::iterator path_iter;
for(path_iter = group.paths_in.begin(); path_iter != group.paths_in.end(); ++path_iter)
{
Path64 path = StripDuplicates(*path_iter, is_joined);
auto path = *path_iter;
StripDuplicates(path, is_joined);
Path64::size_type cnt = path.size();
if (cnt == 0 || ((cnt < 3) && group.end_type == EndType::Polygon))
continue;

View File

@ -1,6 +1,6 @@
/*******************************************************************************
* Author : Angus Johnson *
* Date : 14 February 2023 *
* Date : 22 April 2023 *
* Website : http://www.angusj.com *
* Copyright : Angus Johnson 2010-2023 *
* Purpose : FAST rectangular clipping *
@ -619,7 +619,7 @@ namespace Clipper2Lib {
p1 = cw[i];
if (!p1 || p1->next == p1->prev)
{
cw[i++]->edge = nullptr;
cw[i++] = nullptr;
j = 0;
continue;
}
@ -819,8 +819,8 @@ namespace Clipper2Lib {
Paths64 result;
if (rect_.IsEmpty()) return result;
for (const auto& path : paths)
{
for (const Path64& path : paths)
{
if (path.size() < 3) continue;
path_bounds_ = GetBounds(path);
if (!rect_.Intersects(path_bounds_))
@ -867,9 +867,7 @@ namespace Clipper2Lib {
for (const auto& path : paths)
{
if (path.size() < 2) continue;
Rect64 pathrec = GetBounds(path);
if (!rect_.Intersects(pathrec)) continue;
ExecuteInternal(path);