From 0dc894356b4f3e246fd1fcac15e3e0238d3898df Mon Sep 17 00:00:00 2001 From: Seth Hillbrand Date: Fri, 22 Mar 2024 10:41:42 -0700 Subject: [PATCH] Check singular arcs connection Even if there are no other segments in the line chain, we still should check for arc connections in cases of individual arcs on a line chain (cherry picked from commit 6b915049d174b643989502a96cd8507b50fb2ec2) --- libs/kimath/src/geometry/shape_collisions.cpp | 38 +- qa/data/pcbnew/teardrop_issue_JPC2.kicad_pcb | 538 ++++++++++++++++++ qa/tests/pcbnew/test_zone_filler.cpp | 29 + 3 files changed, 586 insertions(+), 19 deletions(-) create mode 100644 qa/data/pcbnew/teardrop_issue_JPC2.kicad_pcb diff --git a/libs/kimath/src/geometry/shape_collisions.cpp b/libs/kimath/src/geometry/shape_collisions.cpp index c1a0b6612f..a405b1c16d 100644 --- a/libs/kimath/src/geometry/shape_collisions.cpp +++ b/libs/kimath/src/geometry/shape_collisions.cpp @@ -356,31 +356,31 @@ static inline bool Collide( const SHAPE_LINE_CHAIN_BASE& aA, const SHAPE_LINE_CH } } } + } - if( closest_dist > 0 && aActual ) + if( (!aActual && !aLocation ) || closest_dist > 0 ) + { + std::vector chains = { + dynamic_cast( &aA ), + dynamic_cast( &aB ) + }; + + std::vector shapes = { &aA, &aB }; + + for( int ii = 0; ii < 2; ii++ ) { - std::vector chains = { - dynamic_cast( &aA ), - dynamic_cast( &aB ) - }; + const SHAPE_LINE_CHAIN* chain = chains[ii]; + const SHAPE* other = shapes[( ii + 1 ) % 2]; - std::vector shapes = { &aA, &aB }; + if( !chain ) + continue; - for( int ii = 0; ii < 2; ii++ ) + for( size_t jj = 0; jj < chain->ArcCount(); jj++ ) { - const SHAPE_LINE_CHAIN* chain = chains[ii]; - const SHAPE* other = shapes[( ii + 1 ) % 2]; + const SHAPE_ARC& arc = chain->Arc( jj ); - if( !chain ) - continue; - - for( size_t jj = 0; jj < chain->ArcCount(); jj++ ) - { - const SHAPE_ARC& arc = chain->Arc( jj ); - - if( arc.Collide( other, aClearance, aActual, aLocation ) ) - return true; - } + if( arc.Collide( other, aClearance, aActual, aLocation ) ) + return true; } } } diff --git a/qa/data/pcbnew/teardrop_issue_JPC2.kicad_pcb b/qa/data/pcbnew/teardrop_issue_JPC2.kicad_pcb new file mode 100644 index 0000000000..6fa8fe692d --- /dev/null +++ b/qa/data/pcbnew/teardrop_issue_JPC2.kicad_pcb @@ -0,0 +1,538 @@ +(kicad_pcb + (version 20240225) + (generator "pcbnew") + (generator_version "8.99") + (general + (thickness 0.2) + (legacy_teardrops no) + ) + (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 "0.2mm_Polymid_Stiffener") + ) + (setup + (stackup + (layer "F.SilkS" + (type "Top Silk Screen") + ) + (layer "F.Paste" + (type "Top Solder Paste") + ) + (layer "F.Mask" + (type "Top Solder Mask") + (thickness 0.01) + ) + (layer "F.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "dielectric 1" + (type "core") + (thickness 0.11) + (material "FR4") + (epsilon_r 4.5) + (loss_tangent 0.02) + ) + (layer "B.Cu" + (type "copper") + (thickness 0.035) + ) + (layer "B.Mask" + (type "Bottom Solder Mask") + (thickness 0.01) + ) + (layer "B.Paste" + (type "Bottom Solder Paste") + ) + (layer "B.SilkS" + (type "Bottom Silk Screen") + ) + (copper_finish "None") + (dielectric_constraints no) + ) + (pad_to_mask_clearance 0) + (allow_soldermask_bridges_in_footprints no) + (pcbplotparams + (layerselection 0x00713fc_ffffffff) + (plot_on_all_layers_selection 0x0000000_00000000) + (disableapertmacros no) + (usegerberextensions no) + (usegerberattributes yes) + (usegerberadvancedattributes yes) + (creategerberjobfile yes) + (dashed_line_dash_ratio 12.000000) + (dashed_line_gap_ratio 3.000000) + (svgprecision 4) + (plotframeref no) + (viasonmask no) + (mode 1) + (useauxorigin no) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (pdf_front_fp_property_popups yes) + (pdf_back_fp_property_popups yes) + (pdf_metadata yes) + (dxfpolygonmode yes) + (dxfimperialunits yes) + (dxfusepcbnewfont yes) + (psnegative no) + (psa4output no) + (plotreference yes) + (plotvalue yes) + (plotfptext yes) + (plotinvisibletext no) + (sketchpadsonfab no) + (subtractmaskfromsilk yes) + (outputformat 1) + (mirror no) + (drillshape 0) + (scaleselection 1) + (outputdirectory "P-${PROJECT_NUMBER}_${PROJECT_NAME}_${PROJECT_VERSION}_ID${PROJECT_ID}_FAB_OUTPUT") + ) + ) + (net 0 "") + (net 1 "/OUT_CAM0_SCL") + (net 2 "GND") + (net 3 "/SYNC_ZRGB") + (footprint "Don-Con:FFC_Pads_01x22_P0.5mm_3mm-stiffener" + (layer "F.Cu") + (uuid "0d9c340c-3241-4240-8fc1-5e5cf3bb7293") + (at 66.42 53.84) + (property "Reference" "J?" + (at 5.08 0.13 0) + (layer "F.SilkS") + (uuid "8417bdc9-0351-48a0-825d-2796e1b79cad") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Value" "Vision_Module" + (at 0 0 0) + (layer "F.Fab") + (hide yes) + (uuid "239793b8-0cbe-46e8-9d50-3cadc5b7e9a9") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (property "Footprint" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "065943b5-3b59-44e1-90c8-b8bac9a16d80") + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Datasheet" "" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "3fd5f25a-8a01-42e0-bf05-c1fba71d70a3") + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "Description" "Generic connector, single row, 01x22, script generated (kicad-library-utils/schlib/autogen/connector/)" + (at 0 0 0) + (unlocked yes) + (layer "F.Fab") + (hide yes) + (uuid "5cab016d-a8da-4327-8a7d-b7347c4e054d") + (effects + (font + (size 1.27 1.27) + ) + ) + ) + (property "exclude_from_bom" "" + (at 0 0 0) + (layer "F.Fab") + (hide yes) + (uuid "fc255b77-f7a5-448c-8241-4febb1c91c3f") + (effects + (font + (size 1 1) + (thickness 0.15) + ) + ) + ) + (path "/4184da38-e404-408d-b896-4b28993de505") + (attr exclude_from_pos_files exclude_from_bom allow_soldermask_bridges) + (fp_rect + (start -0.37 -1.34) + (end 3.45 5.64) + (stroke + (width 0.05) + (type default) + ) + (fill none) + (layer "F.CrtYd") + (uuid "a2e54004-4382-48fa-a7dd-bbddeef392d9") + ) + (pad "16" smd rect + (at 1.45 2.25) + (size 2.5 0.25) + (layers "F.Cu") + (net 2 "GND") + (pinfunction "Pin_16") + (pintype "passive") + (teardrops + (best_length_ratio 1) + (max_length 2) + (best_width_ratio 1) + (max_width 2) + (curve_points 0) + (filter_ratio 0.9) + (enabled yes) + (allow_two_segments yes) + (prefer_zone_connections yes) + ) + (uuid "32f4a9b4-78ee-4222-b263-7caf63c00a68") + ) + (pad "17" smd rect + (at 1.45 2.75) + (size 2.5 0.25) + (layers "F.Cu") + (net 3 "/SYNC_ZRGB") + (pinfunction "Pin_17") + (pintype "passive") + (teardrops + (best_length_ratio 1) + (max_length 2) + (best_width_ratio 1) + (max_width 2) + (curve_points 0) + (filter_ratio 0.9) + (enabled yes) + (allow_two_segments yes) + (prefer_zone_connections yes) + ) + (uuid "abe63b8e-98e1-48d8-a5b3-7c0086370ce8") + ) + (pad "19" smd rect + (at 1.45 3.75) + (size 2.5 0.25) + (layers "F.Cu") + (net 2 "GND") + (pinfunction "Pin_19") + (pintype "passive") + (teardrops + (best_length_ratio 1) + (max_length 2) + (best_width_ratio 1) + (max_width 2) + (curve_points 0) + (filter_ratio 0.9) + (enabled yes) + (allow_two_segments yes) + (prefer_zone_connections yes) + ) + (uuid "3415eb17-5a12-4928-b675-07f139e9ff5a") + ) + (pad "20" smd rect + (at 1.45 4.25) + (size 2.5 0.25) + (layers "F.Cu") + (net 1 "/OUT_CAM0_SCL") + (pinfunction "Pin_20") + (pintype "passive") + (teardrops + (best_length_ratio 1) + (max_length 2) + (best_width_ratio 1) + (max_width 2) + (curve_points 0) + (filter_ratio 0.9) + (enabled yes) + (allow_two_segments yes) + (prefer_zone_connections yes) + ) + (uuid "b88ad53d-994a-4c09-bf26-d22298fc993d") + ) + ) + (gr_rect + (start 62.82 49.49) + (end 73.01 62.64) + (stroke + (width 0.05) + (type default) + ) + (fill none) + (layer "Edge.Cuts") + (uuid "b232f122-8e7f-486f-bc5a-958de386dd79") + ) + (arc + (start 70.291079 57.4775) + (mid 69.612644 57.930816) + (end 68.812374 58.09) + (width 0.1) + (layer "F.Cu") + (net 1) + (uuid "0363adc7-8077-4556-b969-ea996bb37961") + ) + (arc + (start 66.68 57.52) + (mid 66.001565 57.973316) + (end 65.201295 58.1325) + (width 0.1) + (layer "F.Cu") + (net 2) + (uuid "4ea7fd26-3643-46ba-99cd-843380d8010e") + ) + (arc + (start 66.77 56.06) + (mid 66.091565 56.513316) + (end 65.291295 56.6725) + (width 0.1) + (layer "F.Cu") + (net 2) + (uuid "990688a7-abf7-4f96-b542-8de407f89782") + ) + (arc + (start 70.15 56.01) + (mid 69.471565 56.463316) + (end 68.671295 56.6225) + (width 0.1) + (layer "F.Cu") + (net 3) + (uuid "74be004a-a995-40b2-a8cf-df6c7762b253") + ) + (arc + (start 65.51 57.27) + (mid 66.188435 56.816684) + (end 66.988705 56.6575) + (width 0.1) + (layer "F.Cu") + (net 3) + (uuid "b09cc660-826f-4e9f-9ea2-2f312e884cc8") + ) + (zone + (net 1) + (net_name "/OUT_CAM0_SCL") + (layer "F.Cu") + (uuid "0ebdcfd7-9d4e-4a06-a1b8-1e0152eace0f") + (name "$teardrop_padvia$") + (hatch full 0.1) + (priority 30001) + (attr + (teardrop + (type padvia) + ) + ) + (connect_pads yes + (clearance 0) + ) + (min_thickness 0.0254) + (filled_areas_thickness no) + (fill yes + (thermal_gap 0.5) + (thermal_bridge_width 0.5) + (island_removal_mode 1) + (island_area_min 10) + ) + (polygon + (pts + (xy 69.37702 58.062083) (xy 69.351139 57.965492) (xy 69.12 57.965) (xy 67.869035 58.090258) (xy 69.12 58.151436) + ) + ) + (filled_polygon + (layer "F.Cu") + (pts + (xy 69.37702 58.062083) (xy 69.351139 57.965492) (xy 69.12 57.965) (xy 67.869035 58.090258) (xy 69.12 58.151436) + ) + ) + ) + (zone + (net 3) + (net_name "/SYNC_ZRGB") + (layer "F.Cu") + (uuid "13420f36-7139-4785-83bf-cd596e08f0d3") + (name "$teardrop_padvia$") + (hatch full 0.1) + (priority 30001) + (attr + (teardrop + (type padvia) + ) + ) + (connect_pads yes + (clearance 0) + ) + (min_thickness 0.0254) + (filled_areas_thickness no) + (fill yes + (thermal_gap 0.5) + (thermal_bridge_width 0.5) + (island_removal_mode 1) + (island_area_min 10) + ) + (polygon + (pts + (xy 69.379867 56.553161) (xy 69.341599 56.460774) (xy 67.872416 56.465) (xy 67.869077 56.590382) + (xy 69.12 56.645625) + ) + ) + (filled_polygon + (layer "F.Cu") + (pts + (xy 69.34204 56.464199) (xy 69.3446 56.468019) (xy 69.375156 56.541787) (xy 69.375156 56.550741) + (xy 69.368824 56.557073) (xy 69.368269 56.557287) (xy 69.122155 56.644858) (xy 69.117717 56.645524) + (xy 67.880563 56.590889) (xy 67.872449 56.5871) (xy 67.869383 56.578889) (xy 67.870068 56.553161) + (xy 67.872113 56.476354) (xy 67.875759 56.468177) (xy 67.883774 56.464967) (xy 69.333758 56.460796) + ) + ) + ) + (zone + (net 2) + (net_name "GND") + (layer "F.Cu") + (uuid "547bc73e-9a1c-47c2-a9e5-15eb4c2036ff") + (name "$teardrop_padvia$") + (hatch full 0.1) + (priority 30000) + (attr + (teardrop + (type padvia) + ) + ) + (connect_pads yes + (clearance 0) + ) + (min_thickness 0.0254) + (filled_areas_thickness no) + (fill yes + (thermal_gap 0.5) + (thermal_bridge_width 0.5) + (island_removal_mode 1) + (island_area_min 10) + ) + (polygon + (pts + (xy 66.395255 57.695389) (xy 66.456131 57.774725) (xy 67.871046 57.715) (xy 67.870793 57.589392) + (xy 66.62 57.589837) + ) + ) + (filled_polygon + (layer "F.Cu") + (pts + (xy 66.395255 57.695389) (xy 66.456131 57.774725) (xy 67.871046 57.715) (xy 67.870793 57.589392) + (xy 66.62 57.589837) + ) + ) + ) + (zone + (net 2) + (net_name "GND") + (layer "F.Cu") + (uuid "c5b86935-8e2c-481a-aa6a-59c4ea70522f") + (name "$teardrop_padvia$") + (hatch full 0.1) + (priority 30002) + (attr + (teardrop + (type padvia) + ) + ) + (connect_pads yes + (clearance 0) + ) + (min_thickness 0.0254) + (filled_areas_thickness no) + (fill yes + (thermal_gap 0.5) + (thermal_bridge_width 0.5) + (island_removal_mode 1) + (island_area_min 10) + ) + (polygon + (pts + (xy 66.393659 56.299416) (xy 66.443659 56.386017) (xy 67.878815 56.215) (xy 67.870866 56.0895) (xy 66.62 56.180723) + ) + ) + (filled_polygon + (layer "F.Cu") + (pts + (xy 67.867584 56.093175) (xy 67.871604 56.101177) (xy 67.871612 56.101288) (xy 67.878115 56.203951) + (xy 67.875218 56.212425) (xy 67.867822 56.216309) (xy 67.464104 56.264418) (xy 67.46272 56.2645) + (xy 66.600252 56.2645) (xy 66.57101 56.270316) (xy 66.541768 56.276133) (xy 66.475449 56.320447) + (xy 66.448537 56.36072) (xy 66.441091 56.365694) (xy 66.432308 56.363947) (xy 66.428678 56.36007) + (xy 66.39975 56.309967) (xy 66.398582 56.301091) (xy 66.404033 56.293987) (xy 66.404423 56.293771) + (xy 66.617849 56.18185) (xy 66.622423 56.180546) (xy 67.859084 56.090359) + ) + ) + ) + (zone + (net 3) + (net_name "/SYNC_ZRGB") + (layer "F.Cu") + (uuid "fbfffa8c-a289-41b9-a9fb-ebc86d3e802b") + (name "$teardrop_padvia$") + (hatch full 0.1) + (priority 30000) + (attr + (teardrop + (type padvia) + ) + ) + (connect_pads yes + (clearance 0) + ) + (min_thickness 0.0254) + (filled_areas_thickness no) + (fill yes + (thermal_gap 0.5) + (thermal_bridge_width 0.5) + (island_removal_mode 1) + (island_area_min 10) + ) + (polygon + (pts + (xy 66.364554 56.701366) (xy 66.390436 56.797958) (xy 67.875233 56.715) (xy 67.870965 56.589742) + (xy 66.62 56.59798) + ) + ) + (filled_polygon + (layer "F.Cu") + (pts + (xy 67.867877 56.593189) (xy 67.871352 56.601118) (xy 67.874843 56.703558) (xy 67.8717 56.711943) + (xy 67.863803 56.715638) (xy 66.399929 56.797427) (xy 66.391477 56.794467) (xy 66.387975 56.788773) + (xy 66.367231 56.711357) (xy 66.368399 56.702479) (xy 66.37414 56.697485) (xy 66.617925 56.598819) + (xy 66.622233 56.597965) (xy 67.859584 56.589816) + ) + ) + ) +) diff --git a/qa/tests/pcbnew/test_zone_filler.cpp b/qa/tests/pcbnew/test_zone_filler.cpp index 0718baf619..53e12b86cf 100644 --- a/qa/tests/pcbnew/test_zone_filler.cpp +++ b/qa/tests/pcbnew/test_zone_filler.cpp @@ -270,3 +270,32 @@ BOOST_FIXTURE_TEST_CASE( RegressionSliverZoneFillTests, ZONE_FILL_TEST_FIXTURE ) } } + +BOOST_FIXTURE_TEST_CASE( RegressionTeardropFill, ZONE_FILL_TEST_FIXTURE ) +{ + + std::vector> tests = { { "teardrop_issue_JPC2", 5 } // Arcs with teardrops connecting to pads + }; + + for( auto& [ relPath, count ] : tests ) + { + KI_TEST::LoadBoard( m_settingsManager, relPath, m_board ); + + BOARD_DESIGN_SETTINGS& bds = m_board->GetDesignSettings(); + + KI_TEST::FillZones( m_board.get() ); + + int zoneCount = 0; + + for( ZONE* zone : m_board->Zones() ) + { + if( zone->IsTeardropArea() ) + zoneCount++; + } + + BOOST_CHECK_MESSAGE( zoneCount == count, "Expected " << count << " teardrop zones in " + << relPath << ", found " + << zoneCount ); + } +} +