@@ -660,7 +660,23 @@ def _translated_sketch(sketch: dict[str, Any], offset: Vector3) -> dict[str, Any
return output
def _translated_node ( node : FeaturePlanNode , instance_id : str , offset : Vector3 ) - > FeaturePlanNode :
def _owner_plane_frame ( session : ExecutionSession , selector : dict [ str , Any ] ) - > dict [ str , Any ] | None :
""" 解析 selector 的 owner 特征(reference_plane)注册的显式平面 frame。
#6 pattern 引用重解析:pattern 重放 source( pattern_mirror)时,镜像面
是 selector,其 owner 是 reference_plane 特征;该特征执行时把显式
PlaneSpec 登记为拓扑上下文,这里取出该 frame 供随实例变换使用。
"""
owner = selector . get ( " owner_feature_id " )
if not owner :
return None
for record in session . topology . records_for_feature ( str ( owner ) ) :
if record . kind == " plane " and isinstance ( record . value , PlaneSpec ) :
return record . value . as_dict ( )
return None
def _translated_node ( node : FeaturePlanNode , instance_id : str , offset : Vector3 , session : ExecutionSession ) - > FeaturePlanNode :
params = deepcopy ( node . params )
components = offset
if isinstance ( params . get ( " plane " ) , dict ) and params [ " plane " ] . get ( " origin_mm " ) :
@@ -679,6 +695,45 @@ def _translated_node(node: FeaturePlanNode, instance_id: str, offset: Vector3) -
axis = params . get ( " axis " ) or { }
if axis . get ( " origin_mm " ) :
axis [ " origin_mm " ] = [ float ( axis [ " origin_mm " ] [ index ] ) + components [ index ] for index in range ( 3 ) ]
mirror_plane = params . get ( " mirror_plane " )
if isinstance ( mirror_plane , dict ) and node . atomic_id == " pattern_mirror " :
# #6 pattern 引用重解析:镜像面是 reference_plane 引用,随实例平移
# 到新位置后内联为显式 frame;否则重放时 resolve 到原始面,镜像
# 副本会错误地重合在源特征附近。同时源特征也必须平移后重放:镜像
# 副本 = reflect(源@t, 面@t),只平移面不平移源会落在 2P+t-x 处
# 而非正确位置 2P-x+t。
frame = _owner_plane_frame ( session , mirror_plane )
if frame is None :
raise ValueError ( " mirror plane reference cannot be transformed for pattern replay " )
cloned_selector = deepcopy ( mirror_plane )
cloned_selector [ " frame " ] = {
" origin_mm " : [ frame [ " origin_mm " ] [ index ] + components [ index ] for index in range ( 3 ) ] ,
" x_dir " : list ( frame [ " x_dir " ] ) ,
" normal " : list ( frame [ " normal " ] ) ,
}
params [ " mirror_plane " ] = cloned_selector
transformed_ids : list [ str ] = [ ]
for source_id in node . params . get ( " source_feature_ids " ) or [ ] :
source_node = session . replay_definitions . get ( str ( source_id ) )
if source_node is None :
raise ValueError ( f " mirror pattern source feature { source_id } has no replay definition " )
temp_id = f " { instance_id } .src. { source_id } "
shifted = _translated_node ( source_node , temp_id , offset , session )
if shifted . sketch_id :
source_sketch = session . sketches . get ( str ( source_node . sketch_id ) )
if source_sketch is not None :
temp_sketch_id = f " { temp_id } .sk "
session . sketches [ temp_sketch_id ] = _translated_sketch ( source_sketch , offset )
shifted = FeaturePlanNode (
shifted . feature_id , shifted . atomic_id , shifted . name , shifted . depends_on ,
shifted . params , shifted . selectors , temp_sketch_id ,
shifted . declared_status , shifted . source_feature ,
)
# 临时 replay 定义同样进入 nodes 表(replay_sources 以此过滤)。
session . nodes [ temp_id ] = shifted
session . replay_definitions [ temp_id ] = shifted
transformed_ids . append ( temp_id )
params [ " source_feature_ids " ] = transformed_ids
return FeaturePlanNode ( instance_id , node . atomic_id , node . name , ( ) , params , node . selectors , node . sketch_id , node . declared_status , node . source_feature )
@@ -708,7 +763,7 @@ def _execute_linear_pattern(node: FeaturePlanNode, session: ExecutionSession, ex
dependency = pattern_transform_blocker ( source )
if dependency :
raise ValueError ( f " pattern source uses an unsupported { dependency } " )
cloned = _translated_node ( source , f " { node . feature_id } .p { first } _ { second } . { source . feature_id } " , offset )
cloned = _translated_node ( source , f " { node . feature_id } .p { first } _ { second } . { source . feature_id } " , offset , session )
sketch = session . sketches . get ( str ( source . sketch_id ) )
execute ( cloned , session , _translated_sketch ( sketch , offset ) if sketch else None )
# 5. 记录本阵列的 replay 定义:后续阵列若选中本阵列,按定义递归重放,
@@ -775,7 +830,7 @@ def _mirrored_sketch(sketch: dict[str, Any], plane: PlaneSpec) -> dict[str, Any]
return output
def _mirrored_node ( node : FeaturePlanNode , instance_id : str , plane : PlaneSpec ) - > FeaturePlanNode :
def _mirrored_node ( node : FeaturePlanNode , instance_id : str , plane : PlaneSpec , session : ExecutionSession ) - > FeaturePlanNode :
params = deepcopy ( node . params )
if isinstance ( params . get ( " plane " ) , dict ) :
for key in ( " origin_mm " , " x_dir " , " y_dir " , " normal " ) :
@@ -816,6 +871,44 @@ def _mirrored_node(node: FeaturePlanNode, instance_id: str, plane: PlaneSpec) ->
axis [ " origin_mm " ] = _reflect_point ( axis [ " origin_mm " ] , plane )
if axis . get ( " direction " ) :
axis [ " direction " ] = _reflect_point ( axis [ " direction " ] , plane , vector = True )
mirror_plane = params . get ( " mirror_plane " )
if isinstance ( mirror_plane , dict ) and node . atomic_id == " pattern_mirror " :
# #6 pattern 引用重解析:镜像重放 mirror source 时,其镜像面引用
# 随本实例的镜像面一起反射(内联为显式 frame),否则重放 resolve
# 到原始面,嵌套镜像会退化成与源镜像重合的错误几何。源特征同样
# 反射后重放:镜像副本 = reflect(源@P_B, reflect(面,P_B))。
frame = _owner_plane_frame ( session , mirror_plane )
if frame is None :
raise ValueError ( " mirror plane reference cannot be transformed for pattern replay " )
cloned_selector = deepcopy ( mirror_plane )
cloned_selector [ " frame " ] = {
" origin_mm " : _reflect_point ( frame [ " origin_mm " ] , plane ) ,
" x_dir " : _reflect_point ( frame [ " x_dir " ] , plane , vector = True ) ,
" normal " : _reflect_point ( frame [ " normal " ] , plane , vector = True ) ,
}
params [ " mirror_plane " ] = cloned_selector
transformed_ids : list [ str ] = [ ]
for source_id in node . params . get ( " source_feature_ids " ) or [ ] :
source_node = session . replay_definitions . get ( str ( source_id ) )
if source_node is None :
raise ValueError ( f " mirror pattern source feature { source_id } has no replay definition " )
temp_id = f " { instance_id } .src. { source_id } "
shifted = _mirrored_node ( source_node , temp_id , plane , session )
if shifted . sketch_id :
source_sketch = session . sketches . get ( str ( source_node . sketch_id ) )
if source_sketch is not None :
temp_sketch_id = f " { temp_id } .sk "
session . sketches [ temp_sketch_id ] = _mirrored_sketch ( source_sketch , plane )
shifted = FeaturePlanNode (
shifted . feature_id , shifted . atomic_id , shifted . name , shifted . depends_on ,
shifted . params , shifted . selectors , temp_sketch_id ,
shifted . declared_status , shifted . source_feature ,
)
# 临时 replay 定义同样进入 nodes 表(replay_sources 以此过滤)。
session . nodes [ temp_id ] = shifted
session . replay_definitions [ temp_id ] = shifted
transformed_ids . append ( temp_id )
params [ " source_feature_ids " ] = transformed_ids
return FeaturePlanNode ( instance_id , node . atomic_id , node . name , ( ) , params , node . selectors , node . sketch_id , node . declared_status , node . source_feature )
@@ -831,7 +924,7 @@ def _execute_mirror_pattern(node: FeaturePlanNode, session: ExecutionSession) ->
dependency = pattern_transform_blocker ( source )
if dependency :
raise ValueError ( f " mirror pattern source uses an unsupported { dependency } " )
cloned = _mirrored_node ( source , f " { node . feature_id } .m. { source . feature_id } " , resolution . record . value )
cloned = _mirrored_node ( source , f " { node . feature_id } .m. { source . feature_id } " , resolution . record . value , session )
sketch = session . sketches . get ( str ( source . sketch_id ) )
_execute_node ( cloned , session , _mirrored_sketch ( sketch , resolution . record . value ) if sketch else None )
session . replay_definitions [ node . feature_id ] = node