Fix multichannel tool removing vias from reference rule area

When a copper fill zone shares the same name as a placement rule area,
the multichannel tool's enclosedByArea() queries would match items in
both zones. This caused vias and other routing in the reference area to
be incorrectly removed during repeat layout operations.

Changed findOtherItemsInRuleArea() and findRoutingInRuleArea() to use
the zone's UUID instead of its name when constructing enclosedByArea()
expressions.

Fixes https://gitlab.com/kicad/code/kicad/-/issues/21184
This commit is contained in:
Seth Hillbrand
2026-01-08 08:32:26 -08:00
parent 1a39c8e85f
commit 37d8f151ff
6 changed files with 2719 additions and 31 deletions
+8 -31
View File
@@ -212,8 +212,6 @@ bool MULTICHANNEL_TOOL::findOtherItemsInRuleArea( RULE_AREA* aRuleArea, std::set
return aItems.size() > 0;
}
std::vector<BOARD_ITEM*> result;
PCBEXPR_COMPILER compiler( new PCBEXPR_UNIT_RESOLVER );
PCBEXPR_UCODE ucode;
PCBEXPR_CONTEXT ctx, preflightCtx;
@@ -228,23 +226,13 @@ bool MULTICHANNEL_TOOL::findOtherItemsInRuleArea( RULE_AREA* aRuleArea, std::set
preflightCtx.SetErrorCallback( reportError );
compiler.SetErrorCallback( reportError );
bool restoreBlankName = false;
if( aRuleArea->m_zone->GetZoneName().IsEmpty() )
{
restoreBlankName = true;
aRuleArea->m_zone->SetZoneName( aRuleArea->m_zone->m_Uuid.AsString() );
}
wxString ruleText = wxString::Format( wxT( "A.enclosedByArea('%s')" ), aRuleArea->m_zone->GetZoneName() );
// Use the zone's UUID to identify it uniquely. Using the zone name could match other zones
// with the same name (e.g., a copper fill zone with the same name as a rule area).
wxString ruleText = wxString::Format( wxT( "A.enclosedByArea('%s')" ),
aRuleArea->m_zone->m_Uuid.AsString() );
if( !compiler.Compile( ruleText, &ucode, &preflightCtx ) )
{
if( restoreBlankName )
aRuleArea->m_zone->SetZoneName( wxEmptyString );
return false;
}
auto testAndAdd =
[&]( BOARD_ITEM* aItem )
@@ -270,9 +258,6 @@ bool MULTICHANNEL_TOOL::findOtherItemsInRuleArea( RULE_AREA* aRuleArea, std::set
testAndAdd( drawing );
}
if( restoreBlankName )
aRuleArea->m_zone->SetZoneName( wxEmptyString );
return true;
}
@@ -778,15 +763,10 @@ int MULTICHANNEL_TOOL::findRoutingInRuleArea( RULE_AREA* aRuleArea, std::set<BOA
preflightCtx.SetErrorCallback( reportError );
compiler.SetErrorCallback( reportError );
bool restoreBlankName = false;
if( aRuleArea->m_zone->GetZoneName().IsEmpty() )
{
restoreBlankName = true;
aRuleArea->m_zone->SetZoneName( aRuleArea->m_zone->m_Uuid.AsString() );
}
wxString ruleText = wxString::Format( wxT( "A.enclosedByArea('%s')" ), aRuleArea->m_zone->GetZoneName() );
// Use the zone's UUID to identify it uniquely. Using the zone name could match other zones
// with the same name (e.g., a copper fill zone with the same name as a rule area).
wxString ruleText = wxString::Format( wxT( "A.enclosedByArea('%s')" ),
aRuleArea->m_zone->m_Uuid.AsString() );
auto testAndAdd =
[&]( BOARD_CONNECTED_ITEM* aItem )
@@ -816,9 +796,6 @@ int MULTICHANNEL_TOOL::findRoutingInRuleArea( RULE_AREA* aRuleArea, std::set<BOA
}
}
if( restoreBlankName )
aRuleArea->m_zone->SetZoneName( wxEmptyString );
return count;
}
+651
View File
@@ -0,0 +1,651 @@
(kicad_sch
(version 20250114)
(generator "eeschema")
(generator_version "9.0")
(uuid "9515448d-849e-41c3-ba58-84b8fbdcc0f3")
(paper "A4")
(lib_symbols
(symbol "Amplifier_Operational:TL071"
(pin_names
(offset 0.127)
)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(property "Reference" "U"
(at 0 6.35 0)
(effects
(font
(size 1.27 1.27)
)
(justify left)
)
)
(property "Value" "TL071"
(at 0 3.81 0)
(effects
(font
(size 1.27 1.27)
)
(justify left)
)
)
(property "Footprint" ""
(at 1.27 1.27 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
(at 3.81 3.81 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Description" "Single Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "ki_keywords" "singel opamp"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "ki_fp_filters" "SOIC*3.9x4.9mm*P1.27mm* DIP*W7.62mm* TSSOP*3x3mm*P0.65mm*"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(symbol "TL071_0_1"
(polyline
(pts
(xy -5.08 5.08) (xy 5.08 0) (xy -5.08 -5.08) (xy -5.08 5.08)
)
(stroke
(width 0.254)
(type default)
)
(fill
(type background)
)
)
)
(symbol "TL071_1_1"
(pin input line
(at -7.62 2.54 0)
(length 2.54)
(name "+"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "3"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin input line
(at -7.62 -2.54 0)
(length 2.54)
(name "-"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "2"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin power_in line
(at -2.54 7.62 270)
(length 3.81)
(name "V+"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "7"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin power_in line
(at -2.54 -7.62 90)
(length 3.81)
(name "V-"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "4"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin no_connect line
(at 0 2.54 270)
(length 2.54)
(hide yes)
(name "NC"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "8"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin input line
(at 0 -7.62 90)
(length 5.08)
(name "NULL"
(effects
(font
(size 0.508 0.508)
)
)
)
(number "1"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin input line
(at 2.54 -7.62 90)
(length 6.35)
(name "NULL"
(effects
(font
(size 0.508 0.508)
)
)
)
(number "5"
(effects
(font
(size 1.27 1.27)
)
)
)
)
(pin output line
(at 7.62 0 180)
(length 2.54)
(name "~"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "6"
(effects
(font
(size 1.27 1.27)
)
)
)
)
)
(embedded_fonts no)
)
(symbol "power:GND"
(power)
(pin_numbers
(hide yes)
)
(pin_names
(offset 0)
(hide yes)
)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(property "Reference" "#PWR"
(at 0 -6.35 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Value" "GND"
(at 0 -3.81 0)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Footprint" ""
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Datasheet" ""
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Description" "Power symbol creates a global label with name \"GND\" , ground"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "ki_keywords" "global power"
(at 0 0 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(symbol "GND_0_1"
(polyline
(pts
(xy 0 0) (xy 0 -1.27) (xy 1.27 -1.27) (xy 0 -2.54) (xy -1.27 -1.27) (xy 0 -1.27)
)
(stroke
(width 0)
(type default)
)
(fill
(type none)
)
)
)
(symbol "GND_1_1"
(pin power_in line
(at 0 0 270)
(length 0)
(name "~"
(effects
(font
(size 1.27 1.27)
)
)
)
(number "1"
(effects
(font
(size 1.27 1.27)
)
)
)
)
)
(embedded_fonts no)
)
)
(junction
(at 96.52 80.01)
(diameter 0)
(color 0 0 0 0)
(uuid "33b2848a-8747-46b7-87d8-f1bc14ae4653")
)
(junction
(at 111.76 85.09)
(diameter 0)
(color 0 0 0 0)
(uuid "867289c6-ec33-4c00-999d-bb4e4060c206")
)
(junction
(at 106.68 90.17)
(diameter 0)
(color 0 0 0 0)
(uuid "de43c2a5-5e57-48b9-988b-84bc9bd96d67")
)
(wire
(pts
(xy 104.14 90.17) (xy 106.68 90.17)
)
(stroke
(width 0)
(type default)
)
(uuid "3fe4187e-02a0-420a-80d7-24e17e505db5")
)
(wire
(pts
(xy 111.76 90.17) (xy 111.76 85.09)
)
(stroke
(width 0)
(type default)
)
(uuid "48fd8640-73f3-4b5d-b763-e80469b1d74b")
)
(wire
(pts
(xy 93.98 88.9) (xy 93.98 80.01)
)
(stroke
(width 0)
(type default)
)
(uuid "64ab3749-634e-45c6-9221-8d9d7a48b4ee")
)
(wire
(pts
(xy 101.6 90.17) (xy 101.6 97.79)
)
(stroke
(width 0)
(type default)
)
(uuid "6e49a601-9076-4cde-93f0-43953f065699")
)
(wire
(pts
(xy 101.6 74.93) (xy 115.57 74.93)
)
(stroke
(width 0)
(type default)
)
(uuid "6eb77844-f72b-4ce5-ade8-2658a2785782")
)
(wire
(pts
(xy 115.57 85.09) (xy 111.76 85.09)
)
(stroke
(width 0)
(type default)
)
(uuid "70992769-f309-49ed-9245-7599583827cf")
)
(wire
(pts
(xy 101.6 97.79) (xy 106.68 97.79)
)
(stroke
(width 0)
(type default)
)
(uuid "74ed4bd6-0f23-4b6a-a669-c5a91cf26350")
)
(wire
(pts
(xy 93.98 80.01) (xy 96.52 80.01)
)
(stroke
(width 0)
(type default)
)
(uuid "7ad477c9-3ecf-4f0a-8679-e88db997b5d1")
)
(wire
(pts
(xy 111.76 85.09) (xy 111.76 82.55)
)
(stroke
(width 0)
(type default)
)
(uuid "7f98317b-16be-4706-b754-8a3ca40a7b03")
)
(wire
(pts
(xy 115.57 74.93) (xy 115.57 85.09)
)
(stroke
(width 0)
(type default)
)
(uuid "9416c128-d9e6-4943-8a32-21c711260ff5")
)
(wire
(pts
(xy 96.52 80.01) (xy 96.52 85.09)
)
(stroke
(width 0)
(type default)
)
(uuid "bcdbb5e6-d584-411a-b52a-f6a8a0c02901")
)
(wire
(pts
(xy 106.68 97.79) (xy 106.68 90.17)
)
(stroke
(width 0)
(type default)
)
(uuid "bffd839c-079e-4483-9b81-007cf1288587")
)
(wire
(pts
(xy 106.68 90.17) (xy 111.76 90.17)
)
(stroke
(width 0)
(type default)
)
(uuid "f8d5533a-524e-43bb-9830-1ac421d05beb")
)
(symbol
(lib_id "power:GND")
(at 93.98 88.9 0)
(unit 1)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(dnp no)
(fields_autoplaced yes)
(uuid "9dc62def-a72c-496e-b5f9-31bb5506d98e")
(property "Reference" "#PWR01"
(at 93.98 95.25 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Value" "GND"
(at 93.98 93.98 0)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Footprint" ""
(at 93.98 88.9 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Datasheet" ""
(at 93.98 88.9 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Description" "Power symbol creates a global label with name \"GND\" , ground"
(at 93.98 88.9 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(pin "1"
(uuid "7e87d238-0a93-4a98-a248-7270b0af35f5")
)
(instances
(project ""
(path "/498bac11-840c-4b9c-8c40-95416b6d764e/974a0092-e266-4c17-a0ad-0420d2f0f044"
(reference "#PWR01")
(unit 1)
)
(path "/498bac11-840c-4b9c-8c40-95416b6d764e/a2e4406d-77db-4c93-91c7-9c2044625396"
(reference "#PWR02")
(unit 1)
)
)
)
)
(symbol
(lib_id "Amplifier_Operational:TL071")
(at 104.14 82.55 0)
(unit 1)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(dnp no)
(fields_autoplaced yes)
(uuid "a671b08a-fc68-4691-b431-849564f959d2")
(property "Reference" "U1"
(at 113.03 76.1298 0)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Value" "TL071"
(at 113.03 78.6698 0)
(effects
(font
(size 1.27 1.27)
)
)
)
(property "Footprint" "Package_SO:SOIC-8_5.3x5.3mm_P1.27mm"
(at 105.41 81.28 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Datasheet" "http://www.ti.com/lit/ds/symlink/tl071.pdf"
(at 107.95 78.74 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(property "Description" "Single Low-Noise JFET-Input Operational Amplifiers, DIP-8/SOIC-8"
(at 104.14 82.55 0)
(effects
(font
(size 1.27 1.27)
)
(hide yes)
)
)
(pin "7"
(uuid "00746730-6fc4-4164-b43b-6b6793e2af32")
)
(pin "8"
(uuid "7d824b12-f88f-4454-a10b-ec9dc1cdd64f")
)
(pin "1"
(uuid "68e1d864-0530-4af0-a56a-c369b7b26504")
)
(pin "2"
(uuid "1b97841b-b3f4-44e9-86c0-00001944016f")
)
(pin "4"
(uuid "61236191-b414-47b4-8a5a-b2c1a25f7e0b")
)
(pin "5"
(uuid "2a72b9a7-bfaa-40ed-9ab0-41562e028c4a")
)
(pin "6"
(uuid "4f7c7624-ef67-4ce6-8c54-1387bffb0e10")
)
(pin "3"
(uuid "283f50b2-6ff0-4c56-b4ef-c3c25c139069")
)
(instances
(project ""
(path "/498bac11-840c-4b9c-8c40-95416b6d764e/974a0092-e266-4c17-a0ad-0420d2f0f044"
(reference "U1")
(unit 1)
)
(path "/498bac11-840c-4b9c-8c40-95416b6d764e/a2e4406d-77db-4c93-91c7-9c2044625396"
(reference "U2")
(unit 1)
)
)
)
)
)
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,627 @@
{
"board": {
"3dviewports": [],
"design_settings": {
"defaults": {
"apply_defaults_to_fp_fields": false,
"apply_defaults_to_fp_shapes": false,
"apply_defaults_to_fp_text": false,
"board_outline_line_width": 0.05,
"copper_line_width": 0.2,
"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.05,
"dimension_precision": 4,
"dimension_units": 3,
"dimensions": {
"arrow_length": 1270000,
"extension_offset": 500000,
"keep_text_aligned": true,
"suppress_zeroes": true,
"text_position": 0,
"units_format": 0
},
"fab_line_width": 0.1,
"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.1,
"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.8,
"height": 1.27,
"width": 2.54
},
"silk_line_width": 0.1,
"silk_text_italic": false,
"silk_text_size_h": 1.0,
"silk_text_size_v": 1.0,
"silk_text_thickness": 0.1,
"silk_text_upright": false,
"zones": {
"min_clearance": 0.0
}
},
"diff_pair_dimensions": [],
"drc_exclusions": [],
"meta": {
"version": 2
},
"rule_severities": {
"annular_width": "error",
"clearance": "error",
"connection_width": "warning",
"copper_edge_clearance": "error",
"copper_sliver": "warning",
"courtyards_overlap": "error",
"creepage": "error",
"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_filters_mismatch": "ignore",
"footprint_symbol_mismatch": "warning",
"footprint_type_mismatch": "ignore",
"hole_clearance": "error",
"hole_to_hole": "warning",
"holes_co_located": "warning",
"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": "warning",
"malformed_courtyard": "error",
"microvia_drill_out_of_range": "error",
"mirrored_text_on_front_layer": "warning",
"missing_courtyard": "ignore",
"missing_footprint": "warning",
"net_conflict": "warning",
"nonmirrored_text_on_back_layer": "warning",
"npth_inside_courtyard": "ignore",
"padstack": "warning",
"pth_inside_courtyard": "ignore",
"shorting_items": "error",
"silk_edge_clearance": "warning",
"silk_over_copper": "warning",
"silk_overlap": "warning",
"skew_out_of_range": "error",
"solder_mask_bridge": "error",
"starved_thermal": "error",
"text_height": "warning",
"text_on_edge_cuts": "error",
"text_thickness": "warning",
"through_hole_pad_without_hole": "error",
"too_many_vias": "error",
"track_angle": "error",
"track_dangling": "warning",
"track_segment_length": "error",
"track_width": "error",
"tracks_crossing": "error",
"unconnected_items": "error",
"unresolved_variable": "error",
"via_dangling": "warning",
"zones_intersect": "error"
},
"rules": {
"max_error": 0.005,
"min_clearance": 0.0,
"min_connection": 0.0,
"min_copper_edge_clearance": 0.5,
"min_groove_width": 0.0,
"min_hole_clearance": 0.25,
"min_hole_to_hole": 0.25,
"min_microvia_diameter": 0.2,
"min_microvia_drill": 0.1,
"min_resolved_spokes": 2,
"min_silk_clearance": 0.0,
"min_text_height": 0.8,
"min_text_thickness": 0.08,
"min_through_hole_diameter": 0.3,
"min_track_width": 0.0,
"min_via_annular_width": 0.1,
"min_via_diameter": 0.5,
"solder_mask_to_copper_clearance": 0.0,
"use_height_for_length_calcs": true
},
"teardrop_options": [
{
"td_onpthpad": true,
"td_onroundshapesonly": false,
"td_onsmdpad": true,
"td_ontrackend": false,
"td_onvia": true
}
],
"teardrop_parameters": [
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_round_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_rect_shape",
"td_width_to_size_filter_ratio": 0.9
},
{
"td_allow_use_two_tracks": true,
"td_curve_segcount": 0,
"td_height_ratio": 1.0,
"td_length_ratio": 0.5,
"td_maxheight": 2.0,
"td_maxlen": 1.0,
"td_on_pad_in_zone": false,
"td_target_name": "td_track_end",
"td_width_to_size_filter_ratio": 0.9
}
],
"track_widths": [],
"tuning_pattern_settings": {
"diff_pair_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 1.0
},
"diff_pair_skew_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
},
"single_track_defaults": {
"corner_radius_percentage": 80,
"corner_style": 1,
"max_amplitude": 1.0,
"min_amplitude": 0.2,
"single_sided": false,
"spacing": 0.6
}
},
"via_dimensions": [],
"zones_allow_external_fillets": false
},
"ipc2581": {
"dist": "",
"distpn": "",
"internal_id": "",
"mfg": "",
"mpn": ""
},
"layer_pairs": [],
"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",
"different_unit_footprint": "error",
"different_unit_net": "error",
"duplicate_reference": "error",
"duplicate_sheet_names": "error",
"endpoint_off_grid": "warning",
"extra_units": "error",
"footprint_filter": "ignore",
"footprint_link_issues": "warning",
"four_way_junction": "ignore",
"global_label_dangling": "warning",
"hier_label_mismatch": "error",
"label_dangling": "error",
"label_multiple_wires": "warning",
"lib_symbol_issues": "warning",
"lib_symbol_mismatch": "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": "warning",
"power_pin_not_driven": "error",
"same_local_global_label": "warning",
"similar_label_and_power": "warning",
"similar_labels": "warning",
"similar_power": "warning",
"simulation_model_issue": "ignore",
"single_global_label": "ignore",
"unannotated": "error",
"unconnected_wire_endpoint": "warning",
"undefined_netclass": "error",
"unit_value_mismatch": "error",
"unresolved_variable": "error",
"wire_dangling": "error"
}
},
"libraries": {
"pinned_footprint_libs": [],
"pinned_symbol_libs": []
},
"meta": {
"filename": "issue21184.kicad_pro",
"version": 3
},
"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)",
"priority": 2147483647,
"schematic_color": "rgba(0, 0, 0, 0.000)",
"track_width": 0.2,
"via_diameter": 0.6,
"via_drill": 0.3,
"wire_width": 6
}
],
"meta": {
"version": 4
},
"net_colors": null,
"netclass_assignments": null,
"netclass_patterns": []
},
"pcbnew": {
"last_paths": {
"gencad": "",
"idf": "",
"netlist": "",
"plot": "",
"pos_files": "",
"specctra_dsn": "",
"step": "",
"svg": "",
"vrml": ""
},
"page_layout_descr_file": ""
},
"schematic": {
"annotate_start_num": 0,
"bom_export_filename": "${PROJECTNAME}.csv",
"bom_fmt_presets": [],
"bom_fmt_settings": {
"field_delimiter": ",",
"keep_line_breaks": false,
"keep_tabs": false,
"name": "CSV",
"ref_delimiter": ",",
"ref_range_delimiter": "",
"string_delimiter": "\""
},
"bom_presets": [],
"bom_settings": {
"exclude_dnp": false,
"fields_ordered": [
{
"group_by": false,
"label": "Reference",
"name": "Reference",
"show": true
},
{
"group_by": false,
"label": "Qty",
"name": "${QUANTITY}",
"show": true
},
{
"group_by": true,
"label": "Value",
"name": "Value",
"show": true
},
{
"group_by": true,
"label": "DNP",
"name": "${DNP}",
"show": true
},
{
"group_by": true,
"label": "Exclude from BOM",
"name": "${EXCLUDE_FROM_BOM}",
"show": true
},
{
"group_by": true,
"label": "Exclude from Board",
"name": "${EXCLUDE_FROM_BOARD}",
"show": true
},
{
"group_by": true,
"label": "Footprint",
"name": "Footprint",
"show": true
},
{
"group_by": false,
"label": "Datasheet",
"name": "Datasheet",
"show": true
}
],
"filter_string": "",
"group_symbols": true,
"include_excluded_from_bom": true,
"name": "Default Editing",
"sort_asc": true,
"sort_field": "Reference"
},
"connection_grid_size": 50.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,
"operating_point_overlay_i_precision": 3,
"operating_point_overlay_i_range": "~A",
"operating_point_overlay_v_precision": 3,
"operating_point_overlay_v_range": "~V",
"overbar_offset_ratio": 1.23,
"pin_symbol_size": 25.0,
"text_offset_ratio": 0.15
},
"legacy_lib_dir": "",
"legacy_lib_list": [],
"meta": {
"version": 1
},
"net_format_name": "",
"page_layout_descr_file": "",
"plot_directory": "",
"space_save_all_events": true,
"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_dissipations": false,
"spice_save_all_voltages": false,
"subpart_first_id": 65,
"subpart_id_separator": 0
},
"sheets": [
[
"498bac11-840c-4b9c-8c40-95416b6d764e",
"Root"
],
[
"974a0092-e266-4c17-a0ad-0420d2f0f044",
"Test1"
],
[
"a2e4406d-77db-4c93-91c7-9c2044625396",
"Test2"
]
],
"text_variables": {}
}
@@ -0,0 +1,98 @@
(kicad_sch
(version 20250114)
(generator "eeschema")
(generator_version "9.0")
(uuid "498bac11-840c-4b9c-8c40-95416b6d764e")
(paper "A4")
(lib_symbols)
(sheet
(at 63.5 63.5)
(size 25.4 12.7)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(dnp no)
(fields_autoplaced yes)
(stroke
(width 0.1524)
(type solid)
)
(fill
(color 0 0 0 0.0000)
)
(uuid "974a0092-e266-4c17-a0ad-0420d2f0f044")
(property "Sheetname" "Test1"
(at 63.5 62.7884 0)
(effects
(font
(size 1.27 1.27)
)
(justify left bottom)
)
)
(property "Sheetfile" "Test.kicad_sch"
(at 63.5 76.7846 0)
(effects
(font
(size 1.27 1.27)
)
(justify left top)
)
)
(instances
(project "issue21184"
(path "/498bac11-840c-4b9c-8c40-95416b6d764e"
(page "2")
)
)
)
)
(sheet
(at 63.5 83.82)
(size 25.4 12.7)
(exclude_from_sim no)
(in_bom yes)
(on_board yes)
(dnp no)
(fields_autoplaced yes)
(stroke
(width 0.1524)
(type solid)
)
(fill
(color 0 0 0 0.0000)
)
(uuid "a2e4406d-77db-4c93-91c7-9c2044625396")
(property "Sheetname" "Test2"
(at 63.5 83.1084 0)
(effects
(font
(size 1.27 1.27)
)
(justify left bottom)
)
)
(property "Sheetfile" "Test.kicad_sch"
(at 63.5 97.1046 0)
(effects
(font
(size 1.27 1.27)
)
(justify left top)
)
)
(instances
(project "issue21184"
(path "/498bac11-840c-4b9c-8c40-95416b6d764e"
(page "3")
)
)
)
)
(sheet_instances
(path "/"
(page "1")
)
)
(embedded_fonts no)
)
+92
View File
@@ -331,4 +331,96 @@ BOOST_FIXTURE_TEST_CASE( RepeatLayoutCopiesFootprintProperties, MULTICHANNEL_TES
}
/**
* Test that repeat layout does not remove vias from the reference area when a copper zone
* has the same name as one of the rule areas (issue 21184).
*
* The bug occurred because enclosedByArea() matched zones by name, and when a copper fill zone
* shared a name with a rule area, items enclosed by either zone could be incorrectly affected.
*/
BOOST_FIXTURE_TEST_CASE( RepeatLayoutDoesNotRemoveReferenceVias, MULTICHANNEL_TEST_FIXTURE )
{
KI_TEST::LoadBoard( m_settingsManager, "issue21184/issue21184", m_board );
TOOL_MANAGER toolMgr;
MOCK_TOOLS_HOLDER* toolsHolder = new MOCK_TOOLS_HOLDER;
toolMgr.SetEnvironment( m_board.get(), nullptr, nullptr, nullptr, toolsHolder );
MULTICHANNEL_TOOL* mtTool = new MULTICHANNEL_TOOL;
toolMgr.RegisterTool( mtTool );
mtTool->FindExistingRuleAreas();
auto ruleData = mtTool->GetData();
BOOST_TEST_MESSAGE( wxString::Format( "Found %d rule areas",
static_cast<int>( ruleData->m_areas.size() ) ) );
BOOST_CHECK_EQUAL( ruleData->m_areas.size(), 2 );
if( ruleData->m_areas.size() < 2 )
return;
RULE_AREA* refArea = nullptr;
RULE_AREA* targetArea = nullptr;
for( RULE_AREA& ra : ruleData->m_areas )
{
if( ra.m_ruleName == wxT( "Test1" ) )
refArea = &ra;
else if( ra.m_ruleName == wxT( "Test2" ) )
targetArea = &ra;
}
BOOST_REQUIRE( refArea != nullptr );
BOOST_REQUIRE( targetArea != nullptr );
int refViaCountBefore = 0;
for( PCB_TRACK* track : m_board->Tracks() )
{
if( track->Type() == PCB_VIA_T )
{
PCB_VIA* via = static_cast<PCB_VIA*>( track );
VECTOR2I viaPos = via->GetPosition();
if( refArea->m_zone->Outline()->Contains( viaPos ) )
refViaCountBefore++;
}
}
BOOST_TEST_MESSAGE( wxString::Format( "Reference area vias before repeat: %d", refViaCountBefore ) );
BOOST_CHECK( refViaCountBefore > 0 );
mtTool->CheckRACompatibility( refArea->m_zone );
ruleData->m_compatMap[targetArea].m_doCopy = true;
ruleData->m_options.m_copyPlacement = true;
ruleData->m_options.m_copyRouting = true;
int result = mtTool->RepeatLayout( TOOL_EVENT(), refArea->m_zone );
BOOST_CHECK( result >= 0 );
int refViaCountAfter = 0;
for( PCB_TRACK* track : m_board->Tracks() )
{
if( track->Type() == PCB_VIA_T )
{
PCB_VIA* via = static_cast<PCB_VIA*>( track );
VECTOR2I viaPos = via->GetPosition();
if( refArea->m_zone->Outline()->Contains( viaPos ) )
refViaCountAfter++;
}
}
BOOST_TEST_MESSAGE( wxString::Format( "Reference area vias after repeat: %d", refViaCountAfter ) );
BOOST_CHECK_EQUAL( refViaCountAfter, refViaCountBefore );
}
BOOST_AUTO_TEST_SUITE_END()