@ -140,7 +140,8 @@ DEFAULT_KIND_COST_FACTORS = {
ROUTE_CARRIER_KIND : 1.0 ,
ROUTE_CARRIER_KIND_AUXILIARY_PATH : 2.0 ,
ROUTE_CARRIER_KIND_TERMINAL_ACCESS : 2.0 ,
ROUTE_CARRIER_KIND_ROUTING_RANGE : 40.0 ,
# RoutingRange 是安装板/柜内面域兜底;成本要足够高,避免线槽复用较多时反向抢主路径。
ROUTE_CARRIER_KIND_ROUTING_RANGE : 1000.0 ,
ROUTE_CARRIER_KIND_USER_PATH : 1.0 ,
}
ROUTE_CARRIER_VIEW_STYLES = {
@ -2468,6 +2469,10 @@ def create_user_path_bridges_from_diagnostic_suggestions(doc, diagnostic, projec
" created " : [ ] ,
" duplicates " : 0 ,
" stale_suggestions " : 0 ,
" unconnected_terminal_access_bridge_targets " : 0 ,
" unconnected_terminal_access_user_path_bridges " : 0 ,
" unconnected_terminal_access_bridge_duplicates " : 0 ,
" unconnected_terminal_access_bridge_pair_labels " : [ ] ,
}
if doc is None or not isinstance ( diagnostic , dict ) :
return report
@ -2517,6 +2522,41 @@ def create_user_path_bridges_from_diagnostic_suggestions(doc, diagnostic, projec
) ,
)
report [ " created " ] . append ( bridge )
for item in diagnostic . get ( " unconnected_terminals " , [ ] ) or [ ] :
if not isinstance ( item , dict ) :
continue
access_name = str ( item . get ( " access_carrier " , " " ) or " " ) . strip ( )
nearest_name = str ( item . get ( " nearest_network_carrier_name " , " " ) or " " ) . strip ( )
nearest_label = str ( item . get ( " nearest_network_carrier_label " , " " ) or " " ) . strip ( )
if not access_name or not ( nearest_name or nearest_label ) :
continue
report [ " suggestions " ] + = 1
report [ " unconnected_terminal_access_bridge_targets " ] + = 1
access_carrier = _document_object_by_name ( doc , access_name )
nearest_carrier = _document_object_by_name ( doc , nearest_name )
if nearest_carrier is None and nearest_label :
nearest_carrier = _document_object_by_label ( doc , nearest_label )
if not is_route_carrier ( access_carrier ) or not is_route_carrier ( nearest_carrier ) :
report [ " stale_suggestions " ] + = 1
continue
bridges = create_user_path_bridge_between_objects (
doc ,
access_carrier ,
nearest_carrier ,
project_uuid = project_uuid ,
bridge_kind = " UnconnectedTerminalAccessBridge " ,
)
if bridges :
report [ " created " ] . extend ( bridges )
report [ " unconnected_terminal_access_user_path_bridges " ] + = len ( bridges )
for bridge in bridges :
pair_label = str ( getattr ( bridge , " QetRouteBridgePairLabel " , " " ) or " " ) . strip ( )
if pair_label :
report [ " unconnected_terminal_access_bridge_pair_labels " ] . append ( pair_label )
else :
report [ " duplicates " ] + = 1
report [ " unconnected_terminal_access_bridge_duplicates " ] + = 1
return report
@ -2961,6 +3001,16 @@ def _document_object_by_name(doc, name):
return None
def _document_object_by_label ( doc , label ) :
if doc is None or not label :
return None
label = str ( label or " " ) . strip ( )
for candidate in list ( getattr ( doc , " Objects " , [ ] ) or [ ] ) :
if str ( getattr ( candidate , " Label " , " " ) or " " ) . strip ( ) == label :
return candidate
return None
def cleanup_invalid_source_carriers ( doc ) :
""" Remove generated carriers whose FreeCAD source object is missing or invalid. """
if doc is None :
@ -3137,7 +3187,7 @@ def routing_source_summary(doc):
}
def prepare_layout_space_sources_from_document ( doc , project_uuid = " " ):
def prepare_layout_space_sources_from_document ( doc , project_uuid = " " , include_existing_network = True ):
""" Normalize the current FreeCAD document as an EPLAN-style layout space.
This does not generate the routing path network . It marks source objects so
@ -3174,13 +3224,15 @@ def prepare_layout_space_sources_from_document(doc, project_uuid=""):
except Exception :
pass
return {
payload = {
" wire_duct_sources " : len ( wire_duct_sources ) ,
" support_surface_sources " : len ( support_surface_sources ) ,
" wiring_cut_out_sources " : len ( wiring_cut_out_sources ) ,
" routable_terminals " : len ( _collect_routable_terminals ( doc ) ) ,
" existing_network " : network_summary ( doc ) ,
}
if include_existing_network :
payload [ " existing_network " ] = network_summary ( doc )
return payload
def create_wire_duct_carriers_from_document (
@ -3482,7 +3534,32 @@ def _terminal_local_route_issue(terminal):
continue
points = [ _json_route_point ( item ) for item in point_items if item is not None ]
valid_points = [ point for point in points if point is not None ]
if len ( _normalized_route_points ( valid_points ) ) > = 2 :
normalized_points = _normalized_route_points ( valid_points )
if len ( normalized_points ) > = 2 :
try :
origin = _vector ( TerminalObjects . terminal_origin ( terminal ) )
global_points = [ _terminal_local_point_to_global ( terminal , point ) for point in normalized_points ]
bbox = _terminal_parent_device_bbox ( terminal , origin )
except Exception :
bbox = None
global_points = [ ]
if (
bbox is not None
and global_points
and _point_inside_bbox ( global_points [ - 1 ] , bbox , tolerance = DEFAULT_NODE_TOLERANCE )
) :
invalid_samples . append (
{
" property_name " : property_name ,
" reason " : " local_route_end_inside_device_bbox " ,
" message " : " Local route endpoint is still inside the parent device bounding box. " ,
" raw_sample " : raw [ : 160 ] ,
" valid_point_count " : len ( valid_points ) ,
" local_route_end_point " : _point_payload ( global_points [ - 1 ] ) ,
" endpoint_device_bbox " : _bbox_payload ( bbox , clearance = 0.0 ) ,
}
)
continue
return None
invalid_samples . append (
{
@ -3796,7 +3873,7 @@ def terminal_access_diagnostics(terminal, exit_length=20.0, max_exit_length=None
if not points or _distance ( points [ 0 ] , origin ) > DEFAULT_NODE_TOLERANCE :
points . insert ( 0 , origin )
points = _normalized_route_points ( points )
if len ( points ) > = 2 :
if len ( points ) > = 2 and not _terminal_local_route_end_inside_parent_device ( terminal , points ) :
direction = _normalize ( _subtract ( points [ 1 ] , points [ 0 ] ) ) or App . Vector ( 0 , 0 , 1 )
return {
" requested_exit_length_mm " : max ( float ( exit_length or 0.0 ) , 0.0 ) ,
@ -4033,13 +4110,27 @@ def terminal_access_path_points(terminal, exit_length=20.0, max_exit_length=None
if not points or _distance ( points [ 0 ] , origin ) > DEFAULT_NODE_TOLERANCE :
points . insert ( 0 , origin )
normalized = _normalized_route_points ( points )
if len ( normalized ) > = 2 :
if len ( normalized ) > = 2 and not _terminal_local_route_end_inside_parent_device ( terminal , normalized ) :
return normalized
return _normalized_route_points (
[ origin , _terminal_device_aware_exit_point ( terminal , exit_length , max_exit_length = max_exit_length ) ]
)
def _terminal_local_route_end_inside_parent_device ( terminal , global_points ) :
try :
origin = _vector ( TerminalObjects . terminal_origin ( terminal ) )
bbox = _terminal_parent_device_bbox ( terminal , origin )
except Exception :
bbox = None
normalized = _normalized_route_points ( global_points )
return bool (
bbox is not None
and normalized
and _point_inside_bbox ( normalized [ - 1 ] , bbox , tolerance = DEFAULT_NODE_TOLERANCE )
)
def terminal_access_carrier_for_terminal ( terminal ) :
doc = getattr ( terminal , " Document " , None )
carrier = _live_source_carrier ( doc , terminal )
@ -4407,9 +4498,52 @@ def _terminal_access_target_candidate(network, exit_point, max_distance):
selected = dict ( ranked [ 0 ] )
selected [ " terminal_access_target_rule " ] = " fallback_only "
selected [ " terminal_access_fallback_target " ] = True
selected [ " terminal_access_max_distance_mm " ] = float ( max ( float ( max_distance or 0.0 ) , 0.0 ) )
nearest_main_path = _nearest_terminal_access_main_path_candidate ( network , exit_point )
if nearest_main_path is not None :
selected . update ( _terminal_access_main_path_summary ( nearest_main_path , max_distance ) )
return selected
def _nearest_terminal_access_main_path_candidate ( network , exit_point ) :
candidates = connection_point_candidates (
network ,
exit_point ,
limit = 0 ,
max_distance = 0.0 ,
)
main_path_candidates = [
candidate
for candidate in candidates
if _is_terminal_access_main_path_target ( candidate . get ( " carrier " ) )
]
if not main_path_candidates :
return None
return min (
main_path_candidates ,
key = lambda candidate : float ( candidate . get ( " distance " , 0.0 ) or 0.0 ) ,
)
def _terminal_access_main_path_summary ( candidate , max_distance ) :
carrier = candidate . get ( " carrier " )
distance = float ( candidate . get ( " distance " , 0.0 ) or 0.0 )
max_distance_value = float ( max ( float ( max_distance or 0.0 ) , 0.0 ) )
kind = ( getattr ( carrier , " QetRouteCarrierKind " , " " ) or " " ) . strip ( ) or ROUTE_CARRIER_KIND
name = ( getattr ( carrier , " Name " , " " ) or " " ) . strip ( )
label = ( getattr ( carrier , " Label " , " " ) or " " ) . strip ( ) or name
return {
" nearest_main_path_kind " : kind ,
" nearest_main_path_name " : name ,
" nearest_main_path_label " : label ,
" nearest_main_path_distance_mm " : distance ,
" nearest_main_path_point " : _point_payload ( _vector ( candidate . get ( " point " ) ) ) ,
" nearest_main_path_over_max_distance " : bool (
max_distance_value > 0.0 and distance > max_distance_value
) ,
}
def _set_terminal_access_target_metadata ( carrier , candidate ) :
if carrier is None or not isinstance ( candidate , dict ) :
return
@ -4452,12 +4586,52 @@ def _set_terminal_access_target_metadata(carrier, candidate):
" Whether the terminal access target is only a fallback carrier " ,
" 1 " if bool ( candidate . get ( " terminal_access_fallback_target " , False ) ) else " 0 " ,
)
TerminalObjects . ensure_string_property (
carrier ,
" QetTerminalAccessNearestMainPathKind " ,
PROPERTY_GROUP ,
" Nearest main path carrier kind when TerminalAccess falls back to a routing range " ,
str ( candidate . get ( " nearest_main_path_kind " , " " ) or " " ) ,
)
TerminalObjects . ensure_string_property (
carrier ,
" QetTerminalAccessNearestMainPathName " ,
PROPERTY_GROUP ,
" Nearest main path carrier name when TerminalAccess falls back to a routing range " ,
str ( candidate . get ( " nearest_main_path_name " , " " ) or " " ) ,
)
TerminalObjects . ensure_string_property (
carrier ,
" QetTerminalAccessNearestMainPathLabel " ,
PROPERTY_GROUP ,
" Nearest main path carrier label when TerminalAccess falls back to a routing range " ,
str ( candidate . get ( " nearest_main_path_label " , " " ) or " " ) ,
)
TerminalObjects . ensure_string_property (
carrier ,
" QetTerminalAccessNearestMainPathOverMaxDistance " ,
PROPERTY_GROUP ,
" Whether the nearest main path exceeded the configured terminal access max distance " ,
" 1 " if bool ( candidate . get ( " nearest_main_path_over_max_distance " , False ) ) else " 0 " ,
)
_ensure_float_property (
carrier ,
" QetTerminalAccessTargetDistanceMm " ,
" Distance from terminal local exit to selected access target " ,
float ( candidate . get ( " distance " , 0.0 ) or 0.0 ) ,
)
_ensure_float_property (
carrier ,
" QetTerminalAccessNearestMainPathDistanceMm " ,
" Distance from terminal local exit to the nearest main path when fallback is selected " ,
float ( candidate . get ( " nearest_main_path_distance_mm " , 0.0 ) or 0.0 ) ,
)
_ensure_float_property (
carrier ,
" QetTerminalAccessMaxDistanceMm " ,
" Configured maximum distance allowed for TerminalAccess " ,
float ( candidate . get ( " terminal_access_max_distance_mm " , 0.0 ) or 0.0 ) ,
)
_ensure_integer_property (
carrier ,
" QetTerminalAccessTargetComponentPrimarySegments " ,
@ -4583,6 +4757,7 @@ def create_routing_path_network_from_document(
layout_space = prepare_layout_space_sources_from_document (
doc ,
project_uuid = project_uuid ,
include_existing_network = False ,
)
selected_wire_ducts = [ ]
selected_user_paths = [ ]
@ -5014,29 +5189,40 @@ def nearest_node(network, point):
return best_key , best_distance
def nearest_point_on_network ( network , point ) :
""" Return the closest point on any route-network edge.
def _route_carrier_summary ( carrier ) :
if carrier is None :
return {
" carrier_kind " : " " ,
" carrier_name " : " " ,
" carrier_label " : " " ,
}
name = ( getattr ( carrier , " Name " , " " ) or " " ) . strip ( )
label = ( getattr ( carrier , " Label " , " " ) or " " ) . strip ( ) or name
kind = ( getattr ( carrier , " QetRouteCarrierKind " , " " ) or " " ) . strip ( )
return {
" carrier_kind " : kind ,
" carrier_name " : name ,
" carrier_label " : label ,
}
The point may lie in the middle of a carrier segment . If a TerminalAccess
carrier ends there , the next graph build will split the crossed segment at
that point and create an EPLAN - like jump - in routing point .
"""
def _nearest_point_on_network_payload ( network , point ) :
""" Return closest route-network point and the carrier owning that segment. """
if not isinstance ( network , dict ) :
return None , None
return None
nodes = network . get ( " nodes " , { } ) or { }
edges = network . get ( " edges " , { } ) or { }
if not nodes or not edges :
return None , None
return None
target = _vector ( point )
best_point = None
best_distance = None
best_payload = None
seen = set ( )
for key , neighbors in edges . items ( ) :
start = nodes . get ( key )
if start is None :
continue
for next_key , _weight , _ carrier in neighbors :
for next_key , _weight , carrier in neighbors :
pair = tuple ( sorted ( ( key , next_key ) ) )
if pair in seen :
continue
@ -5046,12 +5232,39 @@ def nearest_point_on_network(network, point):
continue
candidate = _closest_point_on_segment ( target , start , end )
distance = _distance ( target , candidate )
if best_distance is None or distance < best_distance :
best_point = candidate
best_distance = distance
if best_point is not None :
return best_point , best_distance
return nearest_node ( network , target )
if best_payload is None or distance < best_payload [ " distance " ] :
payload = {
" point " : candidate ,
" distance " : float ( distance ) ,
}
payload . update ( _route_carrier_summary ( carrier ) )
best_payload = payload
if best_payload is not None :
return best_payload
node_key , distance = nearest_node ( network , target )
if node_key is None :
return None
return {
" point " : nodes . get ( node_key ) ,
" distance " : float ( distance ) ,
" carrier_kind " : " " ,
" carrier_name " : " " ,
" carrier_label " : " " ,
}
def nearest_point_on_network ( network , point ) :
""" Return the closest point on any route-network edge.
The point may lie in the middle of a carrier segment . If a TerminalAccess
carrier ends there , the next graph build will split the crossed segment at
that point and create an EPLAN - like jump - in routing point .
"""
payload = _nearest_point_on_network_payload ( network , point )
if payload is None :
return None , None
return payload . get ( " point " ) , payload . get ( " distance " )
def connection_point_candidates ( network , point , limit = 8 , max_distance = 0.0 ) :
@ -5927,6 +6140,9 @@ def _terminal_for_access_carrier(carrier):
def _terminal_access_diagnostic_payload ( carrier ) :
terminal = _terminal_for_access_carrier ( carrier )
access_points = _normalized_route_points ( _carrier_points ( carrier ) )
endpoint_device_avoided = str (
getattr ( carrier , " QetTerminalAccessAvoidedEndpointDevice " , " " ) or " "
) . strip ( ) == " 1 "
payload = {
" access_carrier_name " : getattr ( carrier , " Name " , " " ) or " " ,
" access_carrier_label " : getattr ( carrier , " Label " , " " ) or " " ,
@ -5935,6 +6151,15 @@ def _terminal_access_diagnostic_payload(carrier):
" target_label " : ( getattr ( carrier , " QetTerminalAccessTargetLabel " , " " ) or " " ) . strip ( ) ,
" target_rule " : ( getattr ( carrier , " QetTerminalAccessTargetRule " , " " ) or " " ) . strip ( ) ,
" target_distance_mm " : float ( getattr ( carrier , " QetTerminalAccessTargetDistanceMm " , 0.0 ) or 0.0 ) ,
" terminal_access_max_distance_mm " : float ( getattr ( carrier , " QetTerminalAccessMaxDistanceMm " , 0.0 ) or 0.0 ) ,
" nearest_main_path_kind " : ( getattr ( carrier , " QetTerminalAccessNearestMainPathKind " , " " ) or " " ) . strip ( ) ,
" nearest_main_path_name " : ( getattr ( carrier , " QetTerminalAccessNearestMainPathName " , " " ) or " " ) . strip ( ) ,
" nearest_main_path_label " : ( getattr ( carrier , " QetTerminalAccessNearestMainPathLabel " , " " ) or " " ) . strip ( ) ,
" nearest_main_path_distance_mm " : float ( getattr ( carrier , " QetTerminalAccessNearestMainPathDistanceMm " , 0.0 ) or 0.0 ) ,
" nearest_main_path_over_max_distance " : str (
getattr ( carrier , " QetTerminalAccessNearestMainPathOverMaxDistance " , " " ) or " "
) . strip ( ) == " 1 " ,
" endpoint_device_avoided " : endpoint_device_avoided ,
" access_length_mm " : float ( _route_length ( access_points ) ) ,
" access_points " : [ _point_payload ( point ) for point in access_points ] ,
}
@ -5952,6 +6177,13 @@ def _terminal_access_diagnostic_payload(carrier):
" parent_device_element_uuid " : terminal_payload . get ( " parent_device_element_uuid " , " " ) ,
}
)
if endpoint_device_avoided :
try :
bbox = _terminal_parent_device_bbox ( terminal , _vector ( TerminalObjects . terminal_origin ( terminal ) ) )
except Exception :
bbox = None
if bbox is not None :
payload [ " endpoint_device_bbox " ] = _bbox_payload ( bbox , clearance = 0.0 )
return payload
@ -6132,12 +6364,13 @@ def diagnose_routing_path_network(
terminal_access_max_distance = DEFAULT_TERMINAL_ACCESS_MAX_DISTANCE ,
terminal_access_warning_distance = 0.0 ,
adjoining_duct_tolerance = DEFAULT_ADJOINING_DUCT_TOLERANCE ,
route_network = None ,
) :
""" Inspect the generated routing path network without routing wires. """
if doc is None :
raise RoutingNetworkError ( " No FreeCAD document is available. " )
network = build_route_graph( doc , adjoining_duct_tolerance = adjoining_duct_tolerance )
network = route_network if isinstance ( route_network , dict ) else build_route_graph( doc , adjoining_duct_tolerance = adjoining_duct_tolerance )
components = _route_graph_components ( network )
summary = _network_summary_from_graph ( network )
isolated_components = _actionable_isolated_components ( components )
@ -6185,7 +6418,9 @@ def diagnose_routing_path_network(
max_exit_length = terminal_exit_max_length ,
)
exit_point = terminal_access_points [ - 1 ] if terminal_access_points else _terminal_exit_point ( terminal , terminal_exit_length )
nearest_point , distance = nearest_point_on_network ( network , exit_point )
nearest_payload = _nearest_point_on_network_payload ( network , exit_point )
nearest_point = nearest_payload . get ( " point " ) if nearest_payload is not None else None
distance = nearest_payload . get ( " distance " ) if nearest_payload is not None else None
access_carrier = _live_source_carrier ( doc , terminal )
access_live = access_carrier is not None and is_route_carrier ( access_carrier )
too_far = nearest_point is None or ( max_distance > 0.0 and float ( distance or 0.0 ) > max_distance )
@ -6197,11 +6432,17 @@ def diagnose_routing_path_network(
" access_carrier " : getattr ( access_carrier , " Name " , " " ) if access_carrier is not None else " " ,
" nearest_network_distance_mm " : None if distance is None else float ( distance ) ,
" nearest_network_point " : None if nearest_point is None else _point_payload ( nearest_point ) ,
" nearest_network_carrier_kind " : " " if nearest_payload is None else nearest_payload . get ( " carrier_kind " , " " ) ,
" nearest_network_carrier_name " : " " if nearest_payload is None else nearest_payload . get ( " carrier_name " , " " ) ,
" nearest_network_carrier_label " : " " if nearest_payload is None else nearest_payload . get ( " carrier_label " , " " ) ,
" terminal_access_max_distance_mm " : float ( max_distance ) ,
" terminal_exit_length_mm " : float ( max ( float ( terminal_exit_length or 0.0 ) , 0.0 ) ) ,
" terminal_exit_point " : _point_payload ( exit_point ) ,
" code " : " terminal_access_missing " if not access_live else " terminal_access_too_far " ,
}
)
# 未接入端子也保留端子出线折线,方便手测时判断是端子方向错、出线过短,还是主路径入口缺失。
payload . update ( _terminal_access_geometry_payload ( terminal_access_points ) )
unconnected_terminals . append ( payload )
continue
@ -6219,6 +6460,23 @@ def diagnose_routing_path_network(
" code " : " terminal_access_long " ,
}
)
if access_carrier is not None :
access_payload = _terminal_access_diagnostic_payload ( access_carrier )
for key in (
" target_kind " ,
" target_name " ,
" target_label " ,
" target_rule " ,
" target_distance_mm " ,
" nearest_main_path_kind " ,
" nearest_main_path_name " ,
" nearest_main_path_label " ,
" nearest_main_path_distance_mm " ,
" nearest_main_path_over_max_distance " ,
" endpoint_device_avoided " ,
) :
if key in access_payload :
payload [ key ] = access_payload . get ( key )
payload . update ( _terminal_access_geometry_payload ( access_points ) )
long_terminal_accesses . append ( payload )
@ -6530,6 +6788,20 @@ def _diagnostic_terminal_text(sample):
)
def _diagnostic_nearest_network_carrier_text ( sample ) :
if not isinstance ( sample , dict ) :
return " "
label = str ( sample . get ( " nearest_network_carrier_label " , " " ) or " " ) . strip ( )
name = str ( sample . get ( " nearest_network_carrier_name " , " " ) or " " ) . strip ( )
kind = str ( sample . get ( " nearest_network_carrier_kind " , " " ) or " " ) . strip ( )
text = label or name
if not text :
return " "
if kind :
return " {0} ( {1} ) " . format ( text , kind )
return text
def _routing_path_network_diagnostic_message ( diagnostic ) :
if not isinstance ( diagnostic , dict ) :
return " 布线路径网络检查失败:诊断结果无效。 "
@ -6552,17 +6824,29 @@ def _routing_path_network_diagnostic_message(diagnostic):
unconnected = _diagnostic_items ( diagnostic . get ( " unconnected_terminals " , [ ] ) or [ ] )
if unconnected :
sample = unconnected [ 0 ]
message + = " \n 端子未接入: {0} ,距离最近网络 {1} ,当前端子接入最大距离 {2} 。 " . format (
nearest_carrier = _diagnostic_nearest_network_carrier_text ( sample )
nearest_carrier_clause = " ,最近路径 {0} " . format ( nearest_carrier ) if nearest_carrier else " "
message + = " \n 端子未接入: {0} ,距离最近网络 {1} {2} ,当前端子接入最大距离 {3} 。 " . format (
_diagnostic_terminal_text ( sample ) ,
_diagnostic_distance_text ( sample . get ( " nearest_network_distance_mm " ) ) ,
nearest_carrier_clause ,
_diagnostic_distance_text ( sample . get ( " terminal_access_max_distance_mm " ) ) ,
)
long_accesses = _diagnostic_items ( diagnostic . get ( " long_terminal_accesses " , [ ] ) or [ ] )
if long_accesses :
sample = long_accesses [ 0 ]
message + = " \n 端子接入过长: {0} ,接入段 {1} 。 " . format (
target_label = str ( sample . get ( " target_label " , " " ) or sample . get ( " target_name " , " " ) or " " ) . strip ( )
target_kind = str ( sample . get ( " target_kind " , " " ) or " " ) . strip ( )
target_clause = " "
if target_label or target_kind :
target_text = target_label or " 未知目标 "
if target_kind :
target_text = " {0} ( {1} ) " . format ( target_text , target_kind )
target_clause = " ,目标 {0} " . format ( target_text )
message + = " \n 端子接入过长: {0} ,接入段 {1} {2} 。 " . format (
_diagnostic_terminal_text ( sample ) ,
_diagnostic_distance_text ( sample . get ( " terminal_access_length_mm " ) ) ,
target_clause ,
)
capped_exits = _diagnostic_items ( diagnostic . get ( " capped_terminal_exits " , [ ] ) or [ ] )
if capped_exits :
@ -6630,6 +6914,24 @@ def _routing_path_network_diagnostic_message(diagnostic):
)
else :
message + = " \n 线槽未接入端子主网络: {0} 。 " . format ( carrier_text )
fallback_targets = _diagnostic_items ( diagnostic . get ( " terminal_access_fallback_targets " , [ ] ) or [ ] )
if fallback_targets :
sample = fallback_targets [ 0 ]
target_text = sample . get ( " target_label " ) or sample . get ( " target_name " ) or " 布线面 "
nearest_main = sample . get ( " nearest_main_path_label " ) or sample . get ( " nearest_main_path_name " ) or " "
if nearest_main :
message + = " \n 端子接入退回布线面: {0} 接入到 {1} ;最近主路径 {2} ,距离 {3} ,端子接入最大距离 {4} 。 " . format (
_diagnostic_terminal_text ( sample ) ,
target_text ,
nearest_main ,
_diagnostic_distance_text ( sample . get ( " nearest_main_path_distance_mm " ) ) ,
_diagnostic_distance_text ( sample . get ( " terminal_access_max_distance_mm " ) ) ,
)
else :
message + = " \n 端子接入退回布线面: {0} 接入到 {1} ,附近没有可用线槽/UserPath/过线孔主路径。 " . format (
_diagnostic_terminal_text ( sample ) ,
target_text ,
)
isolated = _diagnostic_items ( diagnostic . get ( " isolated_components " , [ ] ) or [ ] )
if isolated :
sample = isolated [ 0 ]