@@ -283,7 +283,8 @@ function resolveDerivedEdgeCandidate(event, intersections, feature) {
283283 if ( ! solidId ) return null ;
284284 const faceKey = Number . isFinite ( faceId ) ? `${ solidId } :${ faceId } ` : null ;
285285
286- // Promote dense closed loops (typically circles) to full-loop edge derive.
286+ // Promote short-segment hits to their boundary loop (polyline semantics),
287+ // while long segments remain individually selectable.
287288 if ( ! edge ?. pathWorld && edgeKey . startsWith ( 'faceedge:' ) ) {
288289 const parts = edgeKey . split ( ':' ) ;
289290 const segIndex = Number ( parts [ parts . length - 1 ] ) ;
@@ -292,25 +293,12 @@ function resolveDerivedEdgeCandidate(event, intersections, feature) {
292293 if ( sid && Number . isFinite ( fid ) && Number . isFinite ( segIndex ) ) {
293294 const loops = api . solids ?. getFaceBoundaryLoops ?. ( `${ sid } :${ fid } ` ) || [ ] ;
294295 const loop = loops . find ( lp => Array . isArray ( lp ?. segmentIndices ) && lp . segmentIndices . includes ( segIndex ) && lp ?. closed ) ;
295- if ( loop && Array . isArray ( loop . points ) && loop . points . length >= 8 ) {
296- const center = new THREE . Vector3 ( ) ;
297- for ( const p of loop . points ) center . add ( p ) ;
298- center . multiplyScalar ( 1 / loop . points . length ) ;
299- let mean = 0 ;
300- const rr = [ ] ;
301- for ( const p of loop . points ) {
302- const r = p . distanceTo ( center ) ;
303- rr . push ( r ) ;
304- mean += r ;
305- }
306- mean /= Math . max ( 1 , rr . length ) ;
307- let varR = 0 ;
308- for ( const r of rr ) {
309- const d = r - mean ;
310- varR += d * d ;
311- }
312- const rel = mean > 1e-8 ? Math . sqrt ( varR / Math . max ( 1 , rr . length ) ) / mean : 1 ;
313- if ( rel <= 0.12 ) {
296+ if ( loop && Array . isArray ( loop . points ) && loop . points . length >= 3 ) {
297+ const segs = api . solids ?. getFaceBoundarySegments ?. ( `${ sid } :${ fid } ` ) || [ ] ;
298+ const seg = segs [ segIndex ] ;
299+ const hoveredLen = seg ?. a && seg ?. b ? seg . a . distanceTo ( seg . b ) : Infinity ;
300+ const shortSegThreshold = 6 ;
301+ if ( Number . isFinite ( hoveredLen ) && hoveredLen <= shortSegThreshold ) {
314302 edge = {
315303 ...edge ,
316304 key : `faceedgeloop:${ sid } :${ fid } :${ loops . indexOf ( loop ) } ` ,
@@ -439,6 +427,23 @@ function resolveDerivedEdgeCandidate(event, intersections, feature) {
439427 const localA = toFaceLocal ( a ) ;
440428 const localB = toFaceLocal ( b ) ;
441429 const localP = hoverWorld ? toFaceLocal ( new THREE . Vector3 ( hoverWorld . x , hoverWorld . y , hoverWorld . z ) ) : null ;
430+ const pathWorldSegments = [ ] ;
431+ const pathLocalSegments = [ ] ;
432+ if ( Array . isArray ( edge ?. pathWorld ) && edge . pathWorld . length >= 2 ) {
433+ for ( let i = 0 ; i + 1 < edge . pathWorld . length ; i ++ ) {
434+ const wa = edge . pathWorld [ i ] ;
435+ const wb = edge . pathWorld [ i + 1 ] ;
436+ if ( ! wa || ! wb ) continue ;
437+ const la = this . worldToSketchLocal ( wa , basis ) ;
438+ const lb = this . worldToSketchLocal ( wb , basis ) ;
439+ if ( ! la || ! lb ) continue ;
440+ pathLocalSegments . push ( { a : la , b : lb } ) ;
441+ pathWorldSegments . push ( {
442+ a : { x : Number ( wa . x || 0 ) , y : Number ( wa . y || 0 ) , z : Number ( wa . z || 0 ) } ,
443+ b : { x : Number ( wb . x || 0 ) , y : Number ( wb . y || 0 ) , z : Number ( wb . z || 0 ) }
444+ } ) ;
445+ }
446+ }
442447 const canonicalEntity = resolvedPrimary ?. entity || edgeHit ?. entity || null ;
443448 const canonicalEntityId = String ( canonicalEntity ?. id || '' ) ;
444449 const canonicalEntityKind = String ( canonicalEntity ?. kind || 'boundary-segment' ) ;
@@ -454,6 +459,8 @@ function resolveDerivedEdgeCandidate(event, intersections, feature) {
454459 aWorld : { x : a . x , y : a . y , z : a . z } ,
455460 bWorld : { x : b . x , y : b . y , z : b . z } ,
456461 midWorld : { x : mid . x , y : mid . y , z : mid . z } ,
462+ pathLocalSegments : pathLocalSegments . length ? pathLocalSegments : null ,
463+ pathWorldSegments : pathWorldSegments . length ? pathWorldSegments : null ,
457464 a : { x : a . x , y : a . y , z : a . z } ,
458465 b : { x : b . x , y : b . y , z : b . z } ,
459466 hoverPoint : hoverPoint ? { ...hoverPoint , world : hoverWorld } : null ,
0 commit comments