'From SqueakNihongo6.1 of 17 April 2004 [latest update: #0] on 15 September 2004 at 10:41:56 pm'! LineMorph subclass: #ODESpringMorph instanceVariableNames: 'morph1 morph2 naturalLength prevClock ' classVariableNames: '' poolDictionaries: '' category: 'ODE-Base-Morph'! !ODESpringMorph commentStamp: 'sumim 9/14/2004 12:56' prior: 0! I am a spring simulated morph for ODE force field provied by the ODECo system. Putting me into a force field (an ODEForceFieldMorph) and adding handles by shift-click me, then place at least one of them to ODE morph as a mass point.! !ODEForceFieldMorph methodsFor: 'submorphs-add/remove' stamp: 'sumim 9/14/2004 00:41'! addMorphFront: aMorph aMorph class = SelectionMorph ifTrue: [^super addMorphFront: aMorph]. super addMorphFront: aMorph. (aMorph noODE) ifFalse: [self addODEObjectFor: aMorph]. "aMorph class == ODEHingeMorph ifFalse: [self submorphs select: [:e | e noODE] thenCollect: [:e | e comeToFront]]"! ! !ODESpringMorph methodsFor: 'accessing' stamp: 'sumim 9/15/2004 12:59'! deltaLength ^ (self p1 - self p2) r - naturalLength! ! !ODESpringMorph methodsFor: 'accessing' stamp: 'sumim 9/15/2004 16:00'! factor ^ 1e-3! ! !ODESpringMorph methodsFor: 'accessing' stamp: 'sumim 9/15/2004 12:06'! force | k x a | a _ self factor. k _ self k. x _ self deltaLength. ^ a * k * x! ! !ODESpringMorph methodsFor: 'accessing' stamp: 'sumim 9/15/2004 12:38'! k ^ self borderWidth * self borderWidth! ! !ODESpringMorph methodsFor: 'accessing' stamp: 'sumim 9/15/2004 12:09'! m1 ^ self weight: morph1! ! !ODESpringMorph methodsFor: 'accessing' stamp: 'sumim 9/15/2004 12:08'! m2 ^ self weight: morph2! ! !ODESpringMorph methodsFor: 'accessing' stamp: 'sumim 9/15/2004 20:00'! p1 ^ morph1 ifNil: [vertices first] ifNotNil: [morph1 center]! ! !ODESpringMorph methodsFor: 'accessing' stamp: 'sumim 9/15/2004 20:00'! p2 ^ morph2 ifNil: [vertices last] ifNotNil: [morph2 center]! ! !ODESpringMorph methodsFor: 'dropping/grabbing' stamp: 'sumim 9/15/2004 12:59'! aboutToBeGrabbedBy: aHand super aboutToBeGrabbedBy: aHand. morph1 _ morph2 _ nil. naturalLength _ (self p1 - self p2) r. ^ self! ! !ODESpringMorph methodsFor: 'editing' stamp: 'sumim 9/14/2004 01:36'! addHandles super addHandles. {handles first. 1. handles last. vertices size} pairsDo: [: handle : verIndex | handle on: #mouseUp send: #setMassAndDropVertex:event:fromHandle: to: self withValue: verIndex]! ! !ODESpringMorph methodsFor: 'editing' stamp: 'sumim 9/15/2004 15:30'! setMassAndDropVertex: ix event: evt fromHandle: handle | candidates mass | self dropVertex: ix event: evt fromHandle: handle. owner ifNil: [^ self]. candidates _ owner morphsAt: handle position. candidates _ candidates reject: [: morph | morph odeBody isNil or: [ morph topRendererOrSelf == (ix = 1 ifTrue: [morph2] ifFalse: [morph1])]]. mass _ candidates isEmpty ifTrue: [nil] ifFalse: [candidates first topRendererOrSelf]. ix = 1 ifTrue: [morph1 _ mass] ifFalse: [morph2 _ mass]! ! !ODESpringMorph methodsFor: 'initialization' stamp: 'sumim 9/15/2004 15:11'! odeInitialize naturalLength _ (self p1 - self p2) r. prevClock _ Time millisecondClockValue! ! !ODESpringMorph methodsFor: 'stepping and presenter' stamp: 'sumim 9/15/2004 19:56'! step | deltaClock currentClock ratio | (owner isKindOf: ODEForceFieldMorph) ifFalse: [^ super step]. (owner isActive) ifTrue: [ deltaClock _ (currentClock _ Time millisecondClockValue) - prevClock. prevClock _ currentClock. ratio _ (deltaClock / owner stepTime) min: 10. self ifNeedToCatchM1Do: [: body | body addForce2D: self f1 * ratio]. self ifNeedToCatchM2Do: [: body | body addForce2D: self f2 * ratio]]. self ifNeedToCatchM1Do: [: body | self p1: morph1 center]. self ifNeedToCatchM2Do: [: body | self p2: morph2 center]. self computeBounds. ^ super step! ! !ODESpringMorph methodsFor: 'stepping and presenter' stamp: 'sumim 9/15/2004 22:39'! stepTime ^ ((owner isKindOf: ODEForceFieldMorph) and: [owner isActive]) ifTrue: [owner stepTime // 10] ifFalse: [50]! ! !ODESpringMorph methodsFor: 'testing' stamp: 'sumim 9/14/2004 00:31'! noODE ^ true! ! !ODESpringMorph methodsFor: 'utilities' stamp: 'sumim 9/15/2004 12:01'! normalize: vector vector isZero ifTrue: [^ Point r: 1.0 degrees: 360 atRandom]. ^ vector / vector r! ! !ODESpringMorph methodsFor: 'utilities' stamp: 'sumim 9/15/2004 12:41'! odeBodyOf: morphOrNil ^ morphOrNil ifNotNil: [morphOrNil odeBody]! ! !ODESpringMorph methodsFor: 'utilities' stamp: 'sumim 9/15/2004 12:41'! weight: morph | body | body _ self odeBodyOf: morph. ^ body ifNil: [Float infinity] ifNotNil: [body massSphere]! ! !ODESpringMorph methodsFor: 'private' stamp: 'sumim 9/15/2004 12:28'! f1 ^ self force * self u1! ! !ODESpringMorph methodsFor: 'private' stamp: 'sumim 9/15/2004 12:55'! f2 ^ self force * self u2! ! !ODESpringMorph methodsFor: 'private' stamp: 'sumim 9/15/2004 15:09'! ifNeedToCatchM1Do: aBlock | body focus | morph1 ifNil: [^ nil]. focus _ ActiveHand mouseFocus. (handles notNil and: [focus notNil and: [handles first == focus]]) ifTrue: [^ nil]. body _ self odeBodyOf: morph1. body ifNotNil: [aBlock value: body]! ! !ODESpringMorph methodsFor: 'private' stamp: 'sumim 9/15/2004 15:30'! ifNeedToCatchM2Do: aBlock | body focus | morph2 ifNil: [^ nil]. focus _ ActiveHand mouseFocus. (handles notNil and: [focus notNil and: [handles last == focus]]) ifTrue: [^ nil]. body _ self odeBodyOf: morph2. body ifNotNil: [aBlock value: body]! ! !ODESpringMorph methodsFor: 'private' stamp: 'sumim 9/15/2004 15:41'! p1: aPoint ^ vertices at: 1 put: aPoint copy! ! !ODESpringMorph methodsFor: 'private' stamp: 'sumim 9/15/2004 15:41'! p2: aPoint ^ vertices at: vertices size put: aPoint copy! ! !ODESpringMorph methodsFor: 'private' stamp: 'sumim 9/15/2004 20:01'! u1 | unitVector m1 m2 | unitVector _ (self normalize: self p1 - self p2) negated. morph1 ifNil: [^ 0.0 asPoint]. morph2 ifNil: [^ unitVector]. m1 _ self m1. m2 _ self m2. ^ unitVector * (m1 / (m1 + m2))! ! !ODESpringMorph methodsFor: 'private' stamp: 'sumim 9/15/2004 16:07'! u2 | unitVector m1 m2 | unitVector _ (self normalize: self p2 - self p1) negated. morph1 ifNil: [^ unitVector]. morph2 ifNil: [^ 0.0 asPoint]. m1 _ self m1. m2 _ self m2. ^ unitVector * (m2 / (m1 + m2))! ! !ODESpringMorph class methodsFor: 'instance creation' stamp: 'sumim 9/14/2004 15:04'! from: startPoint to: endPoint color: lineColor width: lineWidth | spring | spring _ self vertices: {startPoint. endPoint} color: Color black borderWidth: lineWidth borderColor: lineColor. ^ spring odeInitialize; yourself! !