@@ -169,23 +169,43 @@ const approxCurveLength = (a: Point, b: Point): number => {
169169 return ( ab + abHandle + a . handleOut . length + b . handleIn . length ) / 2 ;
170170} ;
171171
172- const calcOptimalOffset = ( a : Coord [ ] , b : Coord [ ] ) : number => {
173- // TODO also reverse
172+ const invertShape = ( shape : Point [ ] ) : Point [ ] => {
173+ const inverted : Point [ ] = [ ] ;
174+ for ( let i = 0 ; i < shape . length ; i ++ ) {
175+ const j = shape . length - i - 1 ;
176+ const p = copyPoint ( shape [ j ] ) ;
177+ p . handleIn . angle += Math . PI ;
178+ p . handleOut . angle += Math . PI ;
179+ inverted . push ( p ) ;
180+ }
181+ return inverted ;
182+ } ;
183+
184+ const optimizeOrder = ( a : Point [ ] , b : Point [ ] ) : Point [ ] => {
174185 const count = a . length ;
175- let min = Infinity ;
176- let minIndex = 0 ;
177- for ( let i = 0 ; i < count ; i ++ ) {
178- let sum = 0 ;
179- for ( let j = 0 ; j < count ; j ++ ) {
180- sum += distance ( a [ j ] , b [ ( j + i ) % count ] ) ;
181- if ( sum > min ) break ;
182- }
183- if ( sum < min ) {
184- min = sum ;
185- minIndex = i ;
186+
187+ let minSum = Infinity ;
188+ let minOffset = 0 ;
189+ let minShape : Point [ ] = [ ] ;
190+
191+ const setMinOffset = ( shape : Point [ ] ) => {
192+ for ( let i = 0 ; i < count ; i ++ ) {
193+ let sum = 0 ;
194+ for ( let j = 0 ; j < count ; j ++ ) {
195+ sum += distance ( a [ j ] , shape [ ( j + i ) % count ] ) ;
196+ if ( sum > minSum ) break ;
197+ }
198+ if ( sum <= minSum ) {
199+ minSum = sum ;
200+ minOffset = i ;
201+ minShape = shape ;
202+ }
186203 }
187- }
188- return minIndex ;
204+ } ;
205+ setMinOffset ( b ) ;
206+ setMinOffset ( invertShape ( b ) ) ;
207+
208+ return offsetShape ( minOffset , minShape ) ;
189209} ;
190210
191211const offsetShape = ( offset : number , shape : Point [ ] ) : Point [ ] => {
@@ -430,31 +450,26 @@ const testBlobMorph = (percentage: number) => {
430450 const points = Math . max ( a . length , b . length ) ;
431451 const aNorm = divideShape ( points , a ) ;
432452 const bNorm = divideShape ( points , b ) ;
433- const offset = calcOptimalOffset ( aNorm , bNorm ) ;
434- const bOffset = offsetShape ( offset , bNorm ) ;
453+ const bOpt = optimizeOrder ( aNorm , bNorm ) ;
435454
436- renderShape ( interpolateBetweenLoop ( percentage , aNorm , bOffset ) ) ;
455+ renderShape ( interpolateBetweenLoop ( percentage , aNorm , bOpt ) ) ;
437456} ;
438457
439458const testShapeMorph = ( percentage : number ) => {
440459 const a = genBlob ( "a" , 0.6 , 0.6 , 0.3 , { x : 0.5 , y : 0.5 } ) ;
441460 const b : Point [ ] = [
442461 point ( 0.55 , 0.5 , 0 , 0 , 0 , 0 ) ,
443- point ( 0.55 , 0.7 , 0 , 0 , 0 , 0 ) ,
444- point ( 0.75 , 0.7 , 0 , 0 , 0 , 0 ) ,
445462 point ( 0.75 , 0.5 , 0 , 0 , 0 , 0 ) ,
463+ point ( 0.75 , 0.7 , 0 , 0 , 0 , 0 ) ,
464+ point ( 0.55 , 0.7 , 0 , 0 , 0 , 0 ) ,
446465 ] ;
447466
448467 const points = Math . max ( a . length , b . length ) ;
449468 const aNorm = divideShape ( points , a ) ;
450469 const bNorm = divideShape ( points , b ) ;
451- const offset = calcOptimalOffset ( aNorm , bNorm ) ;
452- const bOffset = offsetShape ( offset , bNorm ) ;
453- drawInfo ( "offset" , offset )
470+ const bOpt = optimizeOrder ( aNorm , bNorm ) ;
454471
455- // renderShape(a);
456- // renderShape(b);
457- renderShape ( interpolateBetweenLoop ( percentage , aNorm , bOffset ) ) ;
472+ renderShape ( interpolateBetweenLoop ( percentage , aNorm , bOpt ) ) ;
458473} ;
459474
460475const genBlob = (
0 commit comments