'From Squeak3.6 of ''6 October 2003'' [latest update: #5429] on 4 March 2007 at 3:01:30 pm'! "Change Set: earthSwarms Date: 19 February 2007 Author: Bruce O'Neel Please make sure you load the B3DTutorialFix change set as well. Thanks to Boris Gaertner (Boris.Gaertner@gmx.net) for his Ballon 3D tutorial. You use this with: EarthSwarms main. There are three classes. SRTM30Data is a mostly general GTOPO30 data reader. Note the bugs in the class comment. EarthSwarms in the main class which calls on EarthSwarmsPresenterMorph to display things. EarthSwarms has too many places where the three terrain datasets are hard coded. A more general solution, but, not until after 1 April. SRTM30Data is slightly hard coded for my system. The reading routines have hard coded path names. "! Object subclass: #EarthSwarms instanceVariableNames: 'scene terrain ' classVariableNames: '' poolDictionaries: '' category: 'EarthSwarms'! !EarthSwarms commentStamp: 'BEO 3/4/2007 15:01' prior: 0! EarthSwarms main class. Copies from B3DDemoSurfaces. EarthSwarms main. Thanks to Boris Gaertner (Boris.Gaertner@gmx.net) for his Ballon 3D tutorial.! BorderedMorph subclass: #EarthSwarmsPresenterMorph instanceVariableNames: 'wheels frameWidth b3DSceneMorph source textAccessor terrainDisplay dataSetDisplay aButtonDataSet1 aButtonGeneva dataSource ' classVariableNames: '' poolDictionaries: '' category: 'EarthSwarms'! !EarthSwarmsPresenterMorph commentStamp: 'BEO 2/25/2007 16:52' prior: 0! This is a slightly modified copy of B3DSceneExplorerMorph and B3DTutorialScenePresenterMorph.! Object subclass: #SRTM30Data instanceVariableNames: '' classVariableNames: 'GVAData MedData SFData ' poolDictionaries: '' category: 'EarthSwarms'! !SRTM30Data commentStamp: 'BEO 3/4/2007 14:58' prior: 0! This holds the data in the image. This is just for now, but, since it's meant to be one download this minimizes the number of places that it can fubar. Everything is on the class side. We'll have three areas for now. SF Bay area 30-40N, 235-245E. Read from w140n40.Bathmetry.srtm.gz In file coords we read from 39.9958 down to 30, and from -125 to -115. Genoa 44 to 43N, 8-9W. Read from w020n90.Bathmetry.srtm.gz. In file coords read from 44 down to 43, and from 8 to 9. Geneva area. 46 to 46.75N, 6-6.75W. Read from w020n90.Bathmetry.srtm.gz. In file coords we read from 46.75 down to 46 and from 6 to 6.75. The two problems are: - Two hard coded areas with method names to match. - The reading code has the header data for the SRTM30 data hard coded. Usage: SRTM30Data readSFData "Read the San Francisco height data" SRTM30Data readMedData "Read the Mediterranean height data" SRTM30Data medData "Return an array with the San Francisco height data" SRTM30Data sfData "Return an array with the Mediterranean height data" SRTM30Data clearAll "Clear the stored data" BUGS: I must have something slightly wrong because non-square reading doesn't work. All the data you read must be in one file.! !EarthSwarms methodsFor: 'toplevel' stamp: 'BEO 3/3/2007 21:19'! main self main: (SRTM30Data gvaData).! ! !EarthSwarms methodsFor: 'toplevel' stamp: 'BEO 3/2/2007 19:34'! main: inTerrain self setTerrain: inTerrain. self show.! ! !EarthSwarms methodsFor: 'toplevel' stamp: 'BEO 3/3/2007 20:47'! show " EarthSwarms new show" | view | self createScene. (view := EarthSwarmsPresenterMorph new) source: self description: #descriptionScene; scene: scene. view rotateX: 12.0. view clearColor: (Color gray: 0.86). view parent: self. view addFrameAndExplanationField openInWorldExtent: Display extent x//2 @ (Display extent y * 7 // 8).! ! !EarthSwarms methodsFor: 'toplevel' stamp: 'BEO 3/3/2007 21:17'! switchTerrain: flag view: view (flag = 1) ifTrue: [self setTerrain: SRTM30Data gvaData.]. (flag = 3) ifTrue: [self setTerrain: SRTM30Data medData.]. (flag = 2) ifTrue: [self setTerrain: SRTM30Data sfData.]. self createScene. view scene: scene.! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/25/2007 17:41'! createLightsForScene: aScene | light1 light2 light3 light4 | light1 := B3DDirectionalLight new. light1 direction: 100 @ -20 @ 0. light1 lightColor: (B3DMaterialColor color: (Color r: 0.75 g: 0.28 b: 0.28)). scene lights add: light1. light2 := B3DDirectionalLight new. light2 direction: (240 degreesToRadians cos) * 100 @ -20 @ (240 degreesToRadians sin * 100). light2 lightColor: (B3DMaterialColor color: (Color r: 0.25 g: 0.8 b: 0.25)). scene lights add: light2. light3 := B3DDirectionalLight new. light3 direction: (120 degreesToRadians cos) * 100 @ -20 @ (120 degreesToRadians sin * 100). light3 lightColor: (B3DMaterialColor color: (Color r: 0.25 g: 0.25 b: 0.8)). scene lights add: light3. light4 := B3DDirectionalLight new. light4 direction: 0 @ -100 @ -10. light4 lightColor: (B3DMaterialColor color: (Color r: 0.3 g: 0.3 b: 0.02)). scene lights add: light4. ! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 3/1/2007 17:43'! createScene | camera | camera _ B3DCamera new. camera position: 0@0@1000. camera target: 0@0@0. camera fov: 5.0. scene _ B3DScene new. scene defaultCamera: camera. self createSolidsForScene: scene; createLightsForScene: scene.! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 3/2/2007 19:33'! createSolidsForScene: aScene | sceneObj mat | sceneObj _ B3DSceneObject named: 'EarthSwarms Scene'. sceneObj geometry: (self createTrianglesFromArray: terrain). mat := B3DMaterial new. mat shininess: 0.9; emission: (Color gray: 0.22); specularPart: (Color gray: 0.8). sceneObj material: mat. aScene objects add: sceneObj.! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 14:01'! createSolidsForSceneSave: aScene | sceneObj mat | sceneObj _ B3DSceneObject named: 'EarthSwarms Scene'. sceneObj geometry: (self createTriangleGeometry: [:x :y | (x*x + (y*y)) negated exp * x * 4.0] withDerivatives: [:u1 :v1 | (u1*u1 + (v1*v1)) negated exp * 4.0 - ((u1*u1 + (v1*v1)) negated exp * u1 *u1* 8.0)] and: [:u1 :v1 | ((u1*u1 + (v1*v1)) negated exp * u1 *v1* -8.0)] uFrom: -2.0 to:2.0 vFrom: -2.0 to: 2.5 divisionU: 38 divisionV: 42 coloring: nil ). mat := B3DMaterial new. mat shininess: 0.9; emission: (Color gray: 0.22); specularPart: (Color gray: 0.8). sceneObj material: mat. aScene objects add: sceneObj.! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/25/2007 16:48'! createTriangleGeometry: fn withDerivatives: dufn and: dvfn uFrom: xStart to: xStop vFrom: yStart to: yStop divisionU: nroPx divisionV: nroPy coloring: aBlock " here we create a triangle mesh. The scene is created elsewhere. " | stepPx stepPy x y low high idxF vtx face faces mesh vtxNormals vtxColors fnValue | stepPx := xStop - xStart / (nroPx - 1). stepPy := yStop - yStart / (nroPy - 1). vtx _ WriteStream on: (B3DVector3Array new: nroPx * nroPy). dufn notNil ifTrue: [vtxNormals _ WriteStream on: (B3DVector3Array new: nroPx * nroPy)]. aBlock notNil ifTrue: [vtxColors := WriteStream on: (B3DColor4Array new: nroPx * nroPy)]. x := xStart. y := yStart. " compute the vertices " nroPx timesRepeat: [y := yStart. nroPy timesRepeat: [vtx nextPut: (B3DVector3 x: x y: (fnValue := fn value: x value: y) z: y). dufn notNil ifTrue: [vtxNormals nextPut: (B3DVector3 x: (dufn value: x value: y) y: -1.0 z: (dvfn value: x value: y)) safelyNormalized]. aBlock notNil ifTrue: [vtxColors nextPut: (aBlock value: x - xStart/(xStop - xStart) value: y - yStart/(yStop - yStart) value: fnValue)]. y := y + stepPy. ]. x := x + stepPx. ]. faces := B3DIndexedTriangleArray new: (nroPx - 1)*(nroPy - 1)*2. idxF := low := 1. 1 to: nroPx -1 do: [:i | high := low + nroPy. 1 to: nroPy - 1 do: [:j | face := B3DIndexedTriangle with: low + j - 1 with: low + j with: high + j. faces at: idxF put: face. idxF := idxF + 1. face := B3DIndexedTriangle with: low + j - 1 with: high + j with: high + j - 1. faces at: idxF put: face. idxF := idxF + 1. ]. low := high. ]. mesh := B3DIndexedTriangleMesh new. mesh vertices: vtx contents; faces: faces. dufn notNil ifTrue: [mesh vertexNormals: vtxNormals contents]. aBlock notNil ifTrue: [mesh vertexColors: vtxColors contents]. ^mesh ! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 14:13'! createTrianglesFromArray: twoDarray ^self createTrianglesFromArray: twoDarray uFrom: nil to: nil vFrom: nil to: nil. ! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 3/2/2007 20:09'! createTrianglesFromArray: twoDarray uFrom: xStart to: xStop vFrom: yStart to: yStop " here we create a triangle mesh. The scene is created elsewhere. " | x y low high idxF vtx face faces mesh vtxNormals nroPx nroPy lowX highX lowY highY minVal maxVal | lowX := xStart. highX := xStop. lowX ifNil: [lowX := 2.]. highX ifNil: [highX := (twoDarray width) - 1.]. lowY := yStart. highY := yStop. lowY ifNil: [lowY := 2.]. highY ifNil: [highY := (twoDarray height) - 1 .]. nroPx := highX - lowX + 1. nroPy := highY - lowY + 1. minVal := 32767. maxVal := -32767. lowX to: highX do: [:i | lowY to: highY do: [:j | (minVal > (twoDarray at: i at: j) ) ifTrue: [minVal := twoDarray at: i at: j ]. (maxVal < (twoDarray at: i at: j) ) ifTrue: [maxVal := twoDarray at: i at: j ]. ]. ]. vtx := WriteStream on: (B3DVector3Array new: nroPx * nroPy). vtxNormals := WriteStream on: (B3DVector3Array new: nroPx * nroPy). x := lowX. y := lowY. " compute the vertices " nroPx timesRepeat: [y := lowY. nroPy timesRepeat: [vtx nextPut: (B3DVector3 x: (x - lowX - ((highX-lowX)/2.0) ) y: (50 * ((twoDarray at: x at: y) - minVal)/ (maxVal - minVal)) z: (y - lowY - ((highY-lowY)/2.0))). vtxNormals nextPut: (B3DVector3 x: (self dxArray2D: twoDarray x: x y: y) y: -1.0 z: (self dyArray2D: twoDarray x: x y: y)) safelyNormalized. y := y + 1. ]. x := x + 1. ]. faces := B3DIndexedTriangleArray new: (nroPx - 1)*(nroPy - 1)*2. idxF := low := 1. 1 to: nroPx -1 do: [:i | high := low + nroPy. 1 to: nroPy - 1 do: [:j | face := B3DIndexedTriangle with: low + j - 1 with: low + j with: high + j. faces at: idxF put: face. idxF := idxF + 1. face := B3DIndexedTriangle with: low + j - 1 with: high + j with: high + j - 1. faces at: idxF put: face. idxF := idxF + 1. ]. low := high. ]. mesh := B3DIndexedTriangleMesh new. mesh vertices: vtx contents; faces: faces. mesh vertexNormals: vtxNormals contents. ^mesh ! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 3/4/2007 14:57'! descriptionScene ^'Quick Help: The buttons across the top: Data Set 1 - Does nothing for the moment. The button labeled Geneva, when clicked, switches between Geneva, San Francisco, and the area around Genoa Italy. Acceleration works on the Mac, may, or may not, work anywhere else. Dragging the mouse in the window will move the image around.'! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 13:57'! dxArray2D: arr x: x y: y "Return the X derivitive of arr at x,y" | d1 d2 | d1 := (arr at: x at: y) - (arr at: (x - 1) at: y). d2 := (arr at: (x + 1) at: y) - (arr at: x at: y). ^(d2 + d1)/2.0! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 2/26/2007 13:57'! dyArray2D: arr x: x y: y "Return the Y derivitive of arr at x,y" | d1 d2 | d1 := (arr at: x at: y) - (arr at: x at: (y - 1)). d2 := (arr at: x at: (y + 1)) - (arr at: x at: y). ^(d2 + d1)/2.0! ! !EarthSwarms methodsFor: 'support routines' stamp: 'BEO 3/2/2007 19:33'! setTerrain: inTerrain terrain := inTerrain.! ! !EarthSwarms class methodsFor: 'toplevel' stamp: 'BEO 2/25/2007 16:32'! main " EarthSwarms main." EarthSwarms new main. ! ! !EarthSwarms class methodsFor: 'toplevel' stamp: 'BEO 3/2/2007 19:35'! main: inTerrain " EarthSwarms main." | obj | obj := EarthSwarms new. obj setTerrain: inTerrain. obj main. ! ! !EarthSwarms class methodsFor: 'cleanup' stamp: 'BEO 2/19/2007 11:51'! cleanUpProjects "Cleanup extra projects. This doesn't belong here but it's convient" Project allSubInstancesDo: [:p | (p == Project current) ifFalse: [Project deletingProject: p]. ]. ! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 3/2/2007 20:46'! addFrameAndExplanationField | topView | topView := SystemWindow labelled: 'EarthSwarms'. topView addMorph: self fullFrame: (LayoutFrame fractions: (0 @ 0 corner: 1.0 @ 0.8)). topView addMorph: (PluggableTextMorph on: self text: #contents accept: #acceptContents: readSelection: nil menu: #codePaneMenu:shifted:) frame: (0@0.8 corner: 1@1). ^topView! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 16:59'! clearColor: aColor " set the background color of the B3DSceneMorph " b3DSceneMorph color: aColor! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! closeEnabled ^true! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! codePaneMenu: aMenu shifted: shifted "Note that unless we override perform:orSendTo:, PluggableTextController will respond to all menu items in a text pane" | donorMenu | donorMenu _ shifted ifTrue: [ParagraphEditor shiftedYellowButtonMenu] ifFalse: [ParagraphEditor yellowButtonMenu]. ^ aMenu labels: donorMenu labelString lines: donorMenu lineArray selections: donorMenu selections! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! contents ^source perform: textAccessor! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! scene ^b3DSceneMorph scene! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! scene: aScene b3DSceneMorph scene: aScene.! ! !EarthSwarmsPresenterMorph methodsFor: 'accessing' stamp: 'BEO 2/25/2007 17:00'! source: anInstance description: aSymbol source := anInstance. textAccessor := aSymbol.! ! !EarthSwarmsPresenterMorph methodsFor: 'actions' stamp: 'BEO 2/25/2007 16:54'! acceptContents: xx ^true! ! !EarthSwarmsPresenterMorph methodsFor: 'actions' stamp: 'BEO 2/25/2007 16:55'! closeMorph self delete! ! !EarthSwarmsPresenterMorph methodsFor: 'actions' stamp: 'BEO 2/25/2007 16:55'! switchRotationStatus b3DSceneMorph switchRotationStatus! ! !EarthSwarmsPresenterMorph methodsFor: 'change reporting' stamp: 'BEO 2/25/2007 17:03'! layoutChanged | ctrl | super layoutChanged. b3DSceneMorph ifNil: [^self]. b3DSceneMorph extent: (self extent - ((frameWidth * 2)@(frameWidth * 2))). b3DSceneMorph position: (self bounds origin + ((frameWidth)@(frameWidth))). wheels ifNil: [^self]. wheels isEmpty ifTrue: [^self]. ctrl := wheels at: #fov ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: self bounds corner - ctrl extent - (frameWidth@((frameWidth - ctrl extent y) / 2) rounded)]. ctrl := wheels at: #dolly ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: self bounds corner - ctrl extent - ((((frameWidth - ctrl extent x) / 2) rounded)@frameWidth)]. ctrl := wheels at: #rotX ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: (self bounds origin x + (((frameWidth - ctrl extent x) / 2) rounded))@(self bounds corner y - ctrl extent y - frameWidth)]. ctrl := wheels at: #rotY ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: (self bounds origin x + frameWidth)@(self bounds corner y - ctrl extent y - (((frameWidth - ctrl extent y) / 2) rounded))]. ctrl := wheels at: #rotZ ifAbsent: [nil]. ctrl ifNotNil: [ ctrl position: self bounds origin + ((((frameWidth - ctrl extent x) / 2) rounded)@frameWidth)]. ctrl := wheels at: #accel ifAbsent:[nil]. ctrl ifNotNil:[ ctrl position: self bounds origin + (frameWidth @ ((((frameWidth - ctrl extent y) / 2) rounded)))]. ctrl := wheels at: #accel ifAbsent:[nil]. ctrl ifNotNil:[ ctrl position: self bounds origin + (frameWidth @ ((((frameWidth - ctrl extent y) / 2) rounded)))]. ! ! !EarthSwarmsPresenterMorph methodsFor: 'drawing' stamp: 'BEO 2/25/2007 17:02'! drawOn: aCanvas "Don't fill if my b3dScene does it" (b3DSceneMorph notNil and:[b3DSceneMorph color isOpaque]) ifTrue:[ (aCanvas clipRect areasOutside: b3DSceneMorph bounds) do:[:r| aCanvas clipBy: r during:[:cc| super drawOn: cc]. ]. ] ifFalse: [super drawOn: aCanvas].! ! !EarthSwarmsPresenterMorph methodsFor: 'event handling' stamp: 'BEO 2/25/2007 17:02'! handlesMouseDown: evt ^evt yellowButtonPressed ! ! !EarthSwarmsPresenterMorph methodsFor: 'event handling' stamp: 'BEO 2/25/2007 17:03'! mouseDown: evt evt yellowButtonPressed ifTrue: [ self yellowButtonMenu. ^super mouseDown: evt].! ! !EarthSwarmsPresenterMorph methodsFor: 'hardware acceleration' stamp: 'BEO 2/25/2007 17:04'! accelerationEnabled ^b3DSceneMorph ifNil:[false] ifNotNil:[b3DSceneMorph accelerationEnabled].! ! !EarthSwarmsPresenterMorph methodsFor: 'hardware acceleration' stamp: 'BEO 2/25/2007 17:04'! accelerationEnabled: aBool ^b3DSceneMorph ifNotNil:[b3DSceneMorph accelerationEnabled: aBool].! ! !EarthSwarmsPresenterMorph methodsFor: 'hardware acceleration' stamp: 'BEO 2/25/2007 17:05'! toggleAcceleration self accelerationEnabled: self accelerationEnabled not.! ! !EarthSwarmsPresenterMorph methodsFor: 'initialization' stamp: 'BEO 3/3/2007 21:15'! closeButton "No, I have 0 idea why this might be called closeButton" | outerButton aButton str miniWrapper aHelp | outerButton _ AlignmentMorph newRow height: 24. outerButton beTransparent. outerButton hResizing: #spaceFill; vResizing: #shrinkWrap. outerButton addMorph: (aButton _ UpdatingThreePhaseButtonMorph checkBox). aButton target: self; actionSelector: #toggleAcceleration; arguments: #(); getSelector: #accelerationEnabled. outerButton addTransparentSpacerOfSize: (2 @ 0). outerButton addMorph: (aButtonGeneva := SimpleButtonMorph new label: 'Geneva'). aButtonGeneva setBalloonText: (aHelp := 'Select Geneva or San Francisco'). terrainDisplay := 1. aButtonGeneva target: self; actionSelector: #toggleTerrain. outerButton addTransparentSpacerOfSize: (2 @ 0). outerButton addMorph: (aButtonDataSet1 := SimpleButtonMorph new label: 'Data Set 1'). aButtonDataSet1 setBalloonText: (aHelp := 'Choose a data set '). dataSetDisplay := 1. aButtonDataSet1 target: self; actionSelector: #toggleDS1. outerButton addTransparentSpacerOfSize: (2 @ 0). str _ StringMorph contents: 'Accelerate' font: nil. "(StrikeFont familyName: 'NewYork' size: 12)." miniWrapper _ AlignmentMorph newRow hResizing: #shrinkWrap; vResizing: #shrinkWrap. miniWrapper beTransparent addMorphBack: str lock. outerButton addMorphBack: miniWrapper. aButton setBalloonText: (aHelp _ 'Turn on hardware acceleration if supported'). miniWrapper setBalloonText: aHelp; setProperty: #balloonTarget toValue: aButton. ^outerButton! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 17:37'! addCustomMenuItems: aCustomMenu (aCustomMenu isKindOf: MenuMorph) ifTrue: [aCustomMenu addUpdating: #rotationString action: #switchRotationStatus] ifFalse: [aCustomMenu add: 'switch rotation status' action: #switchRotationStatus]. ! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 16:56'! addCustomMenuItems: aCustomMenu hand: aHandMorph super addCustomMenuItems: aCustomMenu hand: aHandMorph. aCustomMenu addLine. self addCustomMenuItems: aCustomMenu. ! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 16:56'! initialize | ctrl | super initialize. color := Color gray: 0.8. frameWidth := 25. b3DSceneMorph := AdvancedB3DScenePresenterMorph new. b3DSceneMorph color: Color white; borderStyle: (BorderStyle width: 1 color: Color black). self addMorphFront: b3DSceneMorph. wheels := Dictionary new. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #addFovAngle:. ctrl factor: -0.07. ctrl setBalloonText: 'FOV'. self addMorphFront: ctrl. wheels at: #fov put: ctrl. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #addDolly:. ctrl factor: 0.005. ctrl beVertical. ctrl setBalloonText: 'Dolly'. self addMorphFront: ctrl. wheels at: #dolly put: ctrl. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #rotateZ:. ctrl beVertical. ctrl setBalloonText: 'z Axis'. self addMorphFront: ctrl. wheels at: #rotZ put: ctrl. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #rotateY:. ctrl setBalloonText: 'y Axis'. self addMorphFront: ctrl. wheels at: #rotY put: ctrl. ctrl := WheelMorph new. ctrl target: b3DSceneMorph. ctrl actionSelector: #rotateX:. ctrl beVertical. ctrl setBalloonText: 'x Axis'. self addMorphFront: ctrl. wheels at: #rotX put: ctrl. ctrl _ self closeButton. self addMorphFront: ctrl. wheels at: #accel put: ctrl. ! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 16:57'! rotationString ^b3DSceneMorph isRotating ifTrue: ['stop rotating'] ifFalse: ['start rotating']! ! !EarthSwarmsPresenterMorph methodsFor: 'menus' stamp: 'BEO 2/25/2007 16:57'! yellowButtonMenu | menu sel | menu _ CustomMenu new. menu title: self class name. self addCustomMenuItems: menu. sel := menu startUp. sel ifNotNil: [self perform: sel]! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:57'! addDolly: a b3DSceneMorph addDolly: a! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:57'! beRotating b3DSceneMorph beRotating! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! defaultColor ^Color gray! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! panBy: a b3DSceneMorph panBy: a! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! rotateX: a b3DSceneMorph rotateX: a! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! rotateY: a b3DSceneMorph rotateY: a! ! !EarthSwarmsPresenterMorph methodsFor: 'visual properties' stamp: 'BEO 2/25/2007 16:58'! rotateZ: a b3DSceneMorph rotateZ: a! ! !EarthSwarmsPresenterMorph methodsFor: 'Earth Swarms Interface ' stamp: 'BEO 3/3/2007 20:46'! parent: parent dataSource := parent.! ! !EarthSwarmsPresenterMorph methodsFor: 'Earth Swarms Interface ' stamp: 'BEO 3/3/2007 21:15'! toggleDS1 "Swaps between DS1 and DS2 displays" dataSetDisplay := dataSetDisplay + 1. (dataSetDisplay > 3) ifTrue: [dataSetDisplay := 1.]. (dataSetDisplay = 1) ifTrue: [aButtonDataSet1 label: 'Data Set 1'.]. (dataSetDisplay = 2) ifTrue: [aButtonDataSet1 label: 'Data Set 2'.]. (dataSetDisplay = 3) ifTrue: [aButtonDataSet1 label: 'Data Set 3'.]. ! ! !EarthSwarmsPresenterMorph methodsFor: 'Earth Swarms Interface ' stamp: 'BEO 3/4/2007 14:57'! toggleTerrain "Swaps between different Terrains" terrainDisplay := terrainDisplay + 1. (terrainDisplay > 3) ifTrue: [terrainDisplay := 1.]. (terrainDisplay = 1) ifTrue: [aButtonGeneva label: 'Geneva'.]. (terrainDisplay = 2) ifTrue: [aButtonGeneva label: 'San Francisco'.]. (terrainDisplay = 3) ifTrue: [aButtonGeneva label: 'Genoa'.]. dataSource switchTerrain: terrainDisplay view: self. ! ! !EarthSwarmsPresenterMorph class methodsFor: 'initialization' stamp: 'BEO 2/25/2007 16:53'! descriptionForPartsBin ^ self partName: 'EarthSwarms' categories: #('3-D') documentation: '3D Earth Data Display'! ! !SRTM30Data methodsFor: 'see class side' stamp: 'BEO 3/3/2007 20:54'! seeClassSide "See the class side"! ! !SRTM30Data class methodsFor: 'initialization' stamp: 'BEO 3/2/2007 19:31'! clearAll "Clear all the data" SRTM30Data clearMed. SRTM30Data clearSF. SRTM30Data clearGVA. ! ! !SRTM30Data class methodsFor: 'initialization' stamp: 'BEO 3/2/2007 19:31'! clearGVA "Clear the GVA data" GVAData := nil.! ! !SRTM30Data class methodsFor: 'initialization' stamp: 'BEO 2/27/2007 19:53'! clearMed "Clear the Mediterranean data" MedData := nil.! ! !SRTM30Data class methodsFor: 'initialization' stamp: 'BEO 2/27/2007 19:53'! clearSF "Clear the SF data" SFData := nil.! ! !SRTM30Data class methodsFor: 'reading data' stamp: 'BEO 3/3/2007 20:32'! readData: fn fileStartLon: fileStartLon fileStartLat: fileStartLat startLon: startLon startLat: startLat lonLen: lonLen latLen: latLen "Read in the data. Pixel size, nrow, ncols, bytesize, and byte order are all hard coded to match GTOPO30 files Reads from fn which has a starting Longitude of fileStartLon and a starting latitude of fileStartLat. Reads starting at startLon and startLat for lonLen and latLen. NOTE: Everything is in DEGREES. Array values are in meters" | ncols nrows pixelSize nullValue values width height startRow startCol startByte bytesPerValue skipBytes inFile word | ncols := 4800. nrows := 6000. bytesPerValue := 2. pixelSize := 0.00833333333333. nullValue := -9999. width := (1 + (latLen / pixelSize)) asInteger. height := (1 + (lonLen / pixelSize)) asInteger. (width > ncols) ifTrue: [self error: 'width of array is greater than ncols']. (height > nrows) ifTrue: [self error: 'height of array is greater than nrows']. values := Array2D width: width height: height. startRow := ((fileStartLat - startLat) / pixelSize) abs asInteger. startCol := ((fileStartLon - startLon) / pixelSize) abs asInteger. startByte := bytesPerValue * ((startRow * ncols) + startCol). (startByte > (bytesPerValue * ncols * nrows)) ifTrue: [self error: 'starting beyond the end of file']. skipBytes := bytesPerValue * (ncols - width). (skipBytes < 0) ifTrue: [self error: 'reading more than ncols worth of data']. inFile := StandardFileStream readOnlyFileNamed: fn. inFile position: startByte. 1 to: width do: [:i | 1 to: height do: [:j | word := ((inFile next asInteger) << 8 + (inFile next asInteger)). (word > 32767 ) ifTrue: [ word := ((word - 1) bitXor: 16rFFFF) negated ]. values at: (height - j + 1) at: i put: word ]. inFile position: (skipBytes + (inFile position)). ]. inFile close. ^values.! ! !SRTM30Data class methodsFor: 'reading data' stamp: 'BEO 3/3/2007 20:35'! readGVAData "Read in the Mediterranean data" GVAData := SRTM30Data readData: '/home/edoneel/earthSwarmsData/srtm30_plus/w020n90.Bathmetry.srtm' fileStartLon: -19.99583 fileStartLat: 89.99583 startLon: 6 startLat: 46.75 lonLen: 0.75 latLen: 0.75. ! ! !SRTM30Data class methodsFor: 'reading data' stamp: 'BEO 3/3/2007 21:02'! readMedData "Read in the Mediterranean data" MedData := SRTM30Data readData: '/home/edoneel/earthSwarmsData/srtm30_plus/w020n90.Bathmetry.srtm' fileStartLon: -19.99583 fileStartLat: 89.99583 startLon: 8 startLat: 44.5 lonLen: 1.0 latLen: 1.0. ! ! !SRTM30Data class methodsFor: 'reading data' stamp: 'BEO 3/2/2007 19:49'! readSFData "Read in the SF data" SFData := SRTM30Data readData: '/home/edoneel/earthSwarmsData/srtm30_plus/w140n40.Bathmetry.srtm' fileStartLon: -139.995833 fileStartLat: 39.99583 startLon: -123 startLat: 38 lonLen: 1 latLen: 1. ! ! !SRTM30Data class methodsFor: 'reading data' stamp: 'BEO 3/2/2007 18:53'! readValaisData "Read in the Mediterranean data" MedData := SRTM30Data readData: '/home/edoneel/earthSwarmsData/srtm30_plus/w020n90.Bathmetry.srtm' fileStartLon: -19.99583 fileStartLat: 89.99583 startLon: 7 startLat: 44.5 lonLen: 1.0 latLen: 1.0. ! ! !SRTM30Data class methodsFor: 'fetch data' stamp: 'BEO 3/2/2007 19:32'! gvaData "Return the data for GVA" ^GVAData! ! !SRTM30Data class methodsFor: 'fetch data' stamp: 'BEO 2/27/2007 20:00'! medData "Return the data for the Mediterranean" ^MedData.! ! !SRTM30Data class methodsFor: 'fetch data' stamp: 'BEO 2/27/2007 20:00'! sfData "Return the data for San Francisco" ^SFData! ! !SRTM30Data class reorganize! ('initialization' clearAll clearGVA clearMed clearSF) ('reading data' readData:fileStartLon:fileStartLat:startLon:startLat:lonLen:latLen: readGVAData readMedData readSFData readValaisData) ('fetch data' gvaData medData sfData) ! !SRTM30Data reorganize! ('see class side' seeClassSide) ! !EarthSwarmsPresenterMorph class reorganize! ('initialization' descriptionForPartsBin) ! EarthSwarmsPresenterMorph removeSelector: #ds1Displayed! EarthSwarmsPresenterMorph removeSelector: #ds2Displayed! EarthSwarmsPresenterMorph removeSelector: #gvaDisplayed! EarthSwarmsPresenterMorph removeSelector: #openInSystemWindow! EarthSwarmsPresenterMorph removeSelector: #sfoDisplayed! EarthSwarmsPresenterMorph removeSelector: #toggleDS2! EarthSwarmsPresenterMorph removeSelector: #toggleGVA! EarthSwarmsPresenterMorph removeSelector: #toggleSFO! !EarthSwarmsPresenterMorph reorganize! ('accessing' addFrameAndExplanationField clearColor: closeEnabled codePaneMenu:shifted: contents scene scene: source:description:) ('actions' acceptContents: closeMorph switchRotationStatus) ('change reporting' layoutChanged) ('drawing' drawOn:) ('event handling' handlesMouseDown: mouseDown:) ('hardware acceleration' accelerationEnabled accelerationEnabled: toggleAcceleration) ('initialization' closeButton) ('menus' addCustomMenuItems: addCustomMenuItems:hand: initialize rotationString yellowButtonMenu) ('visual properties' addDolly: beRotating defaultColor panBy: rotateX: rotateY: rotateZ:) ('Earth Swarms Interface ' parent: toggleDS1 toggleTerrain) ! !EarthSwarms class reorganize! ('toplevel' main main:) ('cleanup' cleanUpProjects) ! EarthSwarms removeSelector: #createGeometry:uFrom:to:vFrom:to:divisionU:divisionV:coloring:! EarthSwarms removeSelector: #createLightsForScene8:! EarthSwarms removeSelector: #createSolidsForScene8:! EarthSwarms removeSelector: #createTriangleGeometryAndTexture:! !EarthSwarms reorganize! ('toplevel' main main: show switchTerrain:view:) ('support routines' createLightsForScene: createScene createSolidsForScene: createSolidsForSceneSave: createTriangleGeometry:withDerivatives:and:uFrom:to:vFrom:to:divisionU:divisionV:coloring: createTrianglesFromArray: createTrianglesFromArray:uFrom:to:vFrom:to: descriptionScene dxArray2D:x:y: dyArray2D:x:y: setTerrain:) !