diff --git a/src/GeoTools-Tests/AbsoluteCoordinatesTest.class.st b/src/GeoTools-Tests/AbsoluteCoordinatesTest.class.st index d35c74a..c9dc9e6 100644 --- a/src/GeoTools-Tests/AbsoluteCoordinatesTest.class.st +++ b/src/GeoTools-Tests/AbsoluteCoordinatesTest.class.st @@ -169,19 +169,6 @@ AbsoluteCoordinatesTest >> testAbsoluteCoordinatesLimitations [ self assert: coord altitudeInMeters equals: 100. ] -{ #category : #tests } -AbsoluteCoordinatesTest >> testAbsoluteCoordinatesPrintOn [ - | coord | - coord := AbsoluteCoordinates new. - self assert: coord printString equals: 'an AbsoluteCoordinates lat --° lon --° alt --m'. - - coord := AbsoluteCoordinates zero. - self assert: coord printString equals: 'an AbsoluteCoordinates lat 0° lon 0° alt 0m'. - - coord := AbsoluteCoordinates frBrest. - self assert: coord printString equals: 'an AbsoluteCoordinates lat 48.3897° lon -4.48333° alt 52m'. -] - { #category : #tests } AbsoluteCoordinatesTest >> testAbsoluteCoordinatesRandom [ | coord | @@ -348,6 +335,86 @@ AbsoluteCoordinatesTest >> testIsZero [ self assert: coord isZero. ] +{ #category : #tests } +AbsoluteCoordinatesTest >> testPrintAltitudeString [ + + self + assert: absCoord printAltitudeString + equals: 'Not valid altitude'. + + self + assert: AbsoluteCoordinates frBrest printAltitudeString + equals: '52m'. + + self + assert: AbsoluteCoordinates zero printAltitudeString + equals: '0m'. + + self + assert: (AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 0) printAltitudeString + equals: 'Not valid altitude'. +] + +{ #category : #tests } +AbsoluteCoordinatesTest >> testPrintLatitudeString [ + + self + assert: absCoord printLatitudeString + equals: 'Not valid latitude'. + + self + assert: AbsoluteCoordinates frBrest printLatitudeString + equals: '48°23''22"N'. + + self + assert: AbsoluteCoordinates zero printLatitudeString + equals: '00°00''00"N'. + + self + assert: (AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 0) printLatitudeString + equals: '00°00''00"N'. +] + +{ #category : #tests } +AbsoluteCoordinatesTest >> testPrintLongitudeString [ + + self + assert: absCoord printLongitudeString + equals: 'Not valid longitude'. + + self + assert: AbsoluteCoordinates frBrest printLongitudeString + equals: '004°29''00"W'. + + self + assert: AbsoluteCoordinates zero printLongitudeString + equals: '000°00''00"E'. + + self + assert: (AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 0) printLongitudeString + equals: '000°00''00"E'. +] + +{ #category : #tests } +AbsoluteCoordinatesTest >> testPrintOn [ + + self + assert: (String streamContents: [ :str | absCoord printOn: str ]) + equals: 'No valid coordinates'. + + self + assert: (String streamContents: [ :str | AbsoluteCoordinates frBrest printOn: str ]) + equals: '48°23''22"N 004°29''00"W 52m'. + + self + assert: (String streamContents: [ :str | AbsoluteCoordinates zero printOn: str ]) + equals: '00°00''00"N 000°00''00"E 0m'. + + self + assert: (String streamContents: [ :str | (AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 0) printOn: str ]) + equals: '00°00''00"N 000°00''00"E'. +] + { #category : #tests } AbsoluteCoordinatesTest >> testRandom [ diff --git a/src/GeoTools-Tests/AbstractAbsoluteCoordinatesPrinterTest.class.st b/src/GeoTools-Tests/AbstractAbsoluteCoordinatesPrinterTest.class.st new file mode 100644 index 0000000..a76a030 --- /dev/null +++ b/src/GeoTools-Tests/AbstractAbsoluteCoordinatesPrinterTest.class.st @@ -0,0 +1,83 @@ +" +An AbstractAbsoluteCoordinatesPrinterTest is a test class for testing the behavior of AbstractAbsoluteCoordinatesPrinter +" +Class { + #name : #AbstractAbsoluteCoordinatesPrinterTest, + #superclass : #TestCase, + #instVars : [ + 'printer' + ], + #category : #'GeoTools-Tests-Coordinates' +} + +{ #category : #testing } +AbstractAbsoluteCoordinatesPrinterTest class >> isAbstract [ + + ^ self == AbstractAbsoluteCoordinatesPrinterTest +] + +{ #category : #private } +AbstractAbsoluteCoordinatesPrinterTest >> coordinatesList [ + + ^ { + AbsoluteCoordinates frBrest. + AbsoluteCoordinates ausSydney. + AbsoluteCoordinates usaNewYork. + AbsoluteCoordinates zero. + (AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 0). + AbsoluteCoordinates new } +] + +{ #category : #accessing } +AbstractAbsoluteCoordinatesPrinterTest >> printerClass [ + + self subclassResponsibility +] + +{ #category : #running } +AbstractAbsoluteCoordinatesPrinterTest >> setUp [ + + super setUp. + + printer := self printerClass new +] + +{ #category : #tests } +AbstractAbsoluteCoordinatesPrinterTest >> testPrintAbsoluteCoordinatesOn [ + + self coordinatesList do: [ :c | + | stream | + stream := String new writeStream. + printer printAbsoluteCoordinates: c on: stream. + self assert: stream contents isString ] +] + +{ #category : #tests } +AbstractAbsoluteCoordinatesPrinterTest >> testPrintAltitudeOn [ + + self coordinatesList do: [ :c | + | stream | + stream := String new writeStream. + printer printAltitude: c altitude on: stream. + self assert: stream contents isString ] +] + +{ #category : #tests } +AbstractAbsoluteCoordinatesPrinterTest >> testPrintLatitudeOn [ + + self coordinatesList do: [ :c | + | stream | + stream := String new writeStream. + printer printLatitude: c latitude on: stream. + self assert: stream contents isString ] +] + +{ #category : #tests } +AbstractAbsoluteCoordinatesPrinterTest >> testPrintLongitudeOn [ + + self coordinatesList do: [ :c | + | stream | + stream := String new writeStream. + printer printLongitude: c longitude on: stream. + self assert: stream contents isString ] +] diff --git a/src/GeoTools-Tests/DMSAbsoluteCoordinatesPrinterTest.class.st b/src/GeoTools-Tests/DMSAbsoluteCoordinatesPrinterTest.class.st new file mode 100644 index 0000000..eed34d6 --- /dev/null +++ b/src/GeoTools-Tests/DMSAbsoluteCoordinatesPrinterTest.class.st @@ -0,0 +1,69 @@ +Class { + #name : #DMSAbsoluteCoordinatesPrinterTest, + #superclass : #AbstractAbsoluteCoordinatesPrinterTest, + #category : #'GeoTools-Tests-Coordinates' +} + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinterTest >> printerClass [ + + ^ DMSAbsoluteCoordinatesPrinter +] + +{ #category : #tests } +DMSAbsoluteCoordinatesPrinterTest >> testCharacterWest [ + "Test changing west character, i.e. using french language" + + | stream | + printer characterWest: $O. + self assert: printer characterWest equals: $O. + + stream := String new writeStream. + printer printAbsoluteCoordinates: AbsoluteCoordinates frBrest on: stream. + self assert: stream contents equals: '48°23''22"N 004°29''00"O 52m'. +] + +{ #category : #tests } +DMSAbsoluteCoordinatesPrinterTest >> testPrintAbsoluteCoordinatesOn2 [ + + | stream | + stream := String new writeStream. + printer printAbsoluteCoordinates: AbsoluteCoordinates frBrest on: stream. + self assert: stream contents equals: '48°23''22"N 004°29''00"W 52m'. + + stream := String new writeStream. + printer printAbsoluteCoordinates: AbsoluteCoordinates zero on: stream. + self assert: stream contents equals: '00°00''00"N 000°00''00"E 0m'. + + stream := String new writeStream. + printer printAbsoluteCoordinates: AbsoluteCoordinates new on: stream. + self assert: stream contents equals: '' + + + +] + +{ #category : #tests } +DMSAbsoluteCoordinatesPrinterTest >> testReset [ + + printer reset +] + +{ #category : #tests } +DMSAbsoluteCoordinatesPrinterTest >> testWithSpaces [ + + | stream | + self deny: printer withSpaces. + + printer withSpaces: true. + self assert: printer withSpaces. + stream := String new writeStream. + printer printAbsoluteCoordinates: AbsoluteCoordinates frBrest on: stream. + self assert: stream contents equals: '48° 23'' 22" N 004° 29'' 00" W 52m'. + + printer withSpaces: false. + self deny: printer withSpaces. + stream := String new writeStream. + printer printAbsoluteCoordinates: AbsoluteCoordinates frBrest on: stream. + self assert: stream contents equals: '48°23''22"N 004°29''00"W 52m'. +] diff --git a/src/GeoTools-Tests/GeodesicUtilsTest.class.st b/src/GeoTools-Tests/GeodesicUtilsTest.class.st index 7a9bc02..c192960 100644 --- a/src/GeoTools-Tests/GeodesicUtilsTest.class.st +++ b/src/GeoTools-Tests/GeodesicUtilsTest.class.st @@ -23,6 +23,34 @@ GeodesicUtilsTest >> tearDown [ super tearDown. ] +{ #category : #tests } +GeodesicUtilsTest >> testAbsoluteCoordinatesAlongGeodesicFromToAtFraction [ + + | coordinates | + coordinates := GeodesicUtils + absoluteCoordinatesAlongGeodesicFrom: + AbsoluteCoordinates zero + to: AbsoluteCoordinates zero + atFraction: 0.5. + + self assert: coordinates class identicalTo: AbsoluteCoordinates +] + +{ #category : #tests } +GeodesicUtilsTest >> testAbsoluteCoordinatesFromDistanceAzimuth [ + "Déplacement vers l’Est sur 1000 m depuis l’équateur (0°, 0°) à azimut 90°" + + | start azimuth distance coord | + + start := AbsoluteCoordinates zero. + azimuth := 90 degreesToRadians radians. + distance := 1000 meters. + + coord := GeodesicUtils absoluteCoordinatesFrom: start distance: distance azimuth: azimuth. + self assert: (coord latitudeInDegrees closeTo: 0). + self assert: (coord longitudeInDegrees closeTo: 0.009013373 precision: 0.0001) +] + { #category : #tests } GeodesicUtilsTest >> testAbsoluteCoordinatesFromDistanceInMAzimuthInRadiansEast [ @@ -197,6 +225,36 @@ GeodesicUtilsTest >> testAbsoluteCoordinatesFromDistanceInMetersAzimuthInRadians self assert: (coord longitudeInDegrees between: expectedLon - delta and: expectedLon + delta). ] +{ #category : #tests } +GeodesicUtilsTest >> testAzimuthFromTo [ + + | from to anAngle | + + from := AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 0. + to := AbsoluteCoordinates latitudeInDegrees: 10 longitudeInDegrees: 0. + + anAngle := GeodesicUtils azimuthFrom: from to: to. + self assert: ((anAngle convertTo: Unit deg) value closeTo: 0 precision: 1e-10). + + from := AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 0. + to := AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 10. + + anAngle := GeodesicUtils azimuthFrom: from to: to. + self assert: ((anAngle convertTo: Unit deg) value closeTo: 90 precision: 1e-10). + + from := AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 0. + to := AbsoluteCoordinates latitudeInDegrees: -10 longitudeInDegrees: 0. + + anAngle := GeodesicUtils azimuthFrom: from to: to. + self assert: ((anAngle convertTo: Unit deg) value closeTo: 180 precision: 1e-10). + + from := AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: 0. + to := AbsoluteCoordinates latitudeInDegrees: 0 longitudeInDegrees: -10. + + anAngle := GeodesicUtils azimuthFrom: from to: to. + self assert: ((anAngle convertTo: Unit deg) value closeTo: 270 precision: 1e-10). +] + { #category : #tests } GeodesicUtilsTest >> testAzimuthInRadiansFromTo [ @@ -260,7 +318,33 @@ GeodesicUtilsTest >> testAzimuthInRadiansFromTo3 [ ] { #category : #tests } -GeodesicUtilsTest >> testDistanceInMetersFromTwoPoints [ +GeodesicUtilsTest >> testDistanceFromTo [ + | originPoint endPoint distance | + + originPoint := AbsoluteCoordinates latitudeInDegrees: 50.06638889 longitudeInDegrees: -5.71472222. + endPoint := AbsoluteCoordinates latitudeInDegrees: 58.64388889 longitudeInDegrees: -3.07. + distance := GeodesicUtils distanceFrom: originPoint to: endPoint. + self assert: ((distance convertTo: Unit meter) value closeTo: 969918.64 precision: 1e-1). + + "0 distance" + originPoint := AbsoluteCoordinates latitudeInDegrees: 42.0 longitudeInDegrees: 3.0. + self assert: (GeodesicUtils distanceFrom: originPoint to: originPoint) equals: 0. + + "meridian line" + originPoint := AbsoluteCoordinates latitudeInDegrees: 10.0 longitudeInDegrees: 0.0. + endPoint := AbsoluteCoordinates latitudeInDegrees: 20.0 longitudeInDegrees: 0.0. + distance := GeodesicUtils distanceFrom: originPoint to: endPoint. + self assert: ((distance convertTo: Unit meter) value closeTo: 1.1131949079327355e6 precision: 1e-6). "Approx. 1111949.266 m between latitudes of 10°" + + "equatorial line" + originPoint := AbsoluteCoordinates latitudeInDegrees: 0.0 longitudeInDegrees: 0.0. + endPoint := AbsoluteCoordinates latitudeInDegrees: 0.0 longitudeInDegrees: 1.0. + distance := GeodesicUtils distanceFrom: originPoint to: endPoint. + self assert: ((distance convertTo: Unit meter) value closeTo: 111319.5 precision: 1e-1). "Approx. 111319.5 m" +] + +{ #category : #tests } +GeodesicUtilsTest >> testDistanceInMetersFromTo [ | originPoint endPoint distanceInM | originPoint := AbsoluteCoordinates latitudeInDegrees: 50.06638889 longitudeInDegrees: -5.71472222. @@ -286,7 +370,7 @@ GeodesicUtilsTest >> testDistanceInMetersFromTwoPoints [ ] { #category : #tests } -GeodesicUtilsTest >> testDistanceInMetersFromTwoPoints2 [ +GeodesicUtilsTest >> testDistanceInMetersFromTo2 [ | origin end dist | "classic" @@ -309,83 +393,224 @@ GeodesicUtilsTest >> testDistanceInMetersFromTwoPoints2 [ ] { #category : #tests } -GeodesicUtilsTest >> testIsAzimuthTowardsArea [ +GeodesicUtilsTest >> testFormulas [ + + self + assert: GeodesicUtils formulas class + equals: GeodesicVincentyFormulas +] + +{ #category : #tests } +GeodesicUtilsTest >> testIsAzimuthTowardsAreaFromAzimuthInDegreesArea [ + + | originPointAbsCoord isAzTowardsArea listPointsArea headingInDegree | + originPointAbsCoord := AbsoluteCoordinates + latitudeInDegrees: 48.28275 + longitudeInDegrees: -4.70553. - | originPointAbsCoord isAzTowardsArea listPointsArea headingInDegree| - - originPointAbsCoord := AbsoluteCoordinates latitudeInDegrees: 48.28275 longitudeInDegrees: -4.70553. - listPointsArea := OrderedCollection new. - listPointsArea add: (AbsoluteCoordinates latitudeInDegrees: 48.32676 longitudeInDegrees: -4.68284). - listPointsArea add: (AbsoluteCoordinates latitudeInDegrees: 48.33995 longitudeInDegrees: -4.65976). - listPointsArea add: (AbsoluteCoordinates latitudeInDegrees: 48.3117 longitudeInDegrees: -4.60466). - listPointsArea add: (AbsoluteCoordinates latitudeInDegrees: 48.29603 longitudeInDegrees: -4.62295). - + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.32676 + longitudeInDegrees: -4.68284). + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.33995 + longitudeInDegrees: -4.65976). + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.3117 + longitudeInDegrees: -4.60466). + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.29603 + longitudeInDegrees: -4.62295). + headingInDegree := 45. - isAzTowardsArea := GeodesicUtils isAzimuthTowardsAreaFrom: originPointAbsCoord azimuth: headingInDegree area: listPointsArea. - - self assert: isAzTowardsArea equals: true. - + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInDegrees: headingInDegree + area: listPointsArea. + + self assert: isAzTowardsArea. + originPointAbsCoord latitudeInDegrees: 48.29603. - - isAzTowardsArea := GeodesicUtils isAzimuthTowardsAreaFrom: originPointAbsCoord azimuth: headingInDegree area: listPointsArea. - - self assert: isAzTowardsArea equals: true. - + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInDegrees: headingInDegree + area: listPointsArea. + + self assert: isAzTowardsArea. + headingInDegree := -45. - - isAzTowardsArea := GeodesicUtils isAzimuthTowardsAreaFrom: originPointAbsCoord azimuth: headingInDegree area: listPointsArea. - - self assert: isAzTowardsArea equals: false. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInDegrees: headingInDegree + area: listPointsArea. + + self deny: isAzTowardsArea. headingInDegree := 90. - - isAzTowardsArea := GeodesicUtils isAzimuthTowardsAreaFrom: originPointAbsCoord azimuth: headingInDegree area: listPointsArea. - - self assert: isAzTowardsArea equals: true. - - originPointAbsCoord := AbsoluteCoordinates latitudeInDegrees: 48.34 longitudeInDegrees: -4.62. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInDegrees: headingInDegree + area: listPointsArea. + + self assert: isAzTowardsArea. + + originPointAbsCoord := AbsoluteCoordinates + latitudeInDegrees: 48.34 + longitudeInDegrees: -4.62. headingInDegree := 225. - - isAzTowardsArea := GeodesicUtils isAzimuthTowardsAreaFrom: originPointAbsCoord azimuth: headingInDegree area: listPointsArea. - - self assert: isAzTowardsArea equals: true. - + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInDegrees: headingInDegree + area: listPointsArea. + self assert: isAzTowardsArea. + headingInDegree := 180. - - isAzTowardsArea := GeodesicUtils isAzimuthTowardsAreaFrom: originPointAbsCoord azimuth: headingInDegree area: listPointsArea. - - self assert: isAzTowardsArea equals: true. - - originPointAbsCoord := AbsoluteCoordinates latitudeInDegrees: 48.01 longitudeInDegrees: -4.62. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInDegrees: headingInDegree + area: listPointsArea. + + self assert: isAzTowardsArea. + + originPointAbsCoord := AbsoluteCoordinates + latitudeInDegrees: 48.01 + longitudeInDegrees: -4.62. headingInDegree := 45. - - isAzTowardsArea := GeodesicUtils isAzimuthTowardsAreaFrom: originPointAbsCoord azimuth: headingInDegree area: listPointsArea. - - self assert: isAzTowardsArea equals: false. - - + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInDegrees: headingInDegree + area: listPointsArea. + + self deny: isAzTowardsArea +] + +{ #category : #tests } +GeodesicUtilsTest >> testIsAzimuthTowardsAreaFromAzimuthInRadiansArea [ + + | originPointAbsCoord isAzTowardsArea listPointsArea headingInDegree | + originPointAbsCoord := AbsoluteCoordinates + latitudeInDegrees: 48.28275 + longitudeInDegrees: -4.70553. + + listPointsArea := OrderedCollection new. + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.32676 + longitudeInDegrees: -4.68284). + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.33995 + longitudeInDegrees: -4.65976). + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.3117 + longitudeInDegrees: -4.60466). + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.29603 + longitudeInDegrees: -4.62295). + + headingInDegree := 45. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInRadians: headingInDegree degreesToRadians + area: listPointsArea. + + self assert: isAzTowardsArea. + + originPointAbsCoord latitudeInDegrees: 48.29603. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInRadians: headingInDegree degreesToRadians + area: listPointsArea. + + self assert: isAzTowardsArea. + + headingInDegree := -45. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInRadians: headingInDegree degreesToRadians + area: listPointsArea. + + self deny: isAzTowardsArea. + + headingInDegree := 90. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInRadians: headingInDegree degreesToRadians + area: listPointsArea. + + self assert: isAzTowardsArea. + + originPointAbsCoord := AbsoluteCoordinates + latitudeInDegrees: 48.34 + longitudeInDegrees: -4.62. + headingInDegree := 225. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInRadians: headingInDegree degreesToRadians + area: listPointsArea. + + self assert: isAzTowardsArea. + + headingInDegree := 180. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInRadians: headingInDegree degreesToRadians + area: listPointsArea. + + self assert: isAzTowardsArea. + + originPointAbsCoord := AbsoluteCoordinates + latitudeInDegrees: 48.01 + longitudeInDegrees: -4.62. + headingInDegree := 45. + + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInRadians: headingInDegree degreesToRadians + area: listPointsArea. + + self deny: isAzTowardsArea ] { #category : #tests } GeodesicUtilsTest >> testIsAzimuthTowardsRectangleArea [ - | originPointAbsCoord isAzTowardsArea listPointsArea headingInDegree| - - originPointAbsCoord := AbsoluteCoordinates latitudeInDegrees: 48.20146040354154 longitudeInDegrees: -4.492. - + | originPointAbsCoord isAzTowardsArea listPointsArea headingInDegree | + originPointAbsCoord := AbsoluteCoordinates + latitudeInDegrees: 48.20146040354154 + longitudeInDegrees: -4.492. + listPointsArea := OrderedCollection new. - listPointsArea add: (AbsoluteCoordinates latitudeInDegrees: 48.20998 longitudeInDegrees: -4.493). - listPointsArea add: (AbsoluteCoordinates latitudeInDegrees: 48.20998 longitudeInDegrees: -4.491). - listPointsArea add: (AbsoluteCoordinates latitudeInDegrees: 48.208 longitudeInDegrees: -4.491). - listPointsArea add: (AbsoluteCoordinates latitudeInDegrees: 48.208 longitudeInDegrees: -4.493). - + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.20998 + longitudeInDegrees: -4.493). + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.20998 + longitudeInDegrees: -4.491). + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.208 + longitudeInDegrees: -4.491). + listPointsArea add: (AbsoluteCoordinates + latitudeInDegrees: 48.208 + longitudeInDegrees: -4.493). + headingInDegree := 0. - isAzTowardsArea := GeodesicUtils isAzimuthTowardsAreaFrom: originPointAbsCoord azimuth: headingInDegree area: listPointsArea. - - self assert: isAzTowardsArea equals: true. - + isAzTowardsArea := GeodesicUtils + isAzimuthTowardsAreaFrom: originPointAbsCoord + azimuthInDegrees: headingInDegree + area: listPointsArea. + + self assert: isAzTowardsArea ] diff --git a/src/GeoTools/AbsoluteCoordinates.class.st b/src/GeoTools/AbsoluteCoordinates.class.st index b29710d..8fe7086 100644 --- a/src/GeoTools/AbsoluteCoordinates.class.st +++ b/src/GeoTools/AbsoluteCoordinates.class.st @@ -737,13 +737,66 @@ AbsoluteCoordinates >> normalizeLatitudeInDegrees: aValueInDegrees [ ^ aValueInDegrees ] +{ #category : #printing } +AbsoluteCoordinates >> printAltitudeOn: aStream [ + + self altitude + ifNil: [ aStream nextPutAll: 'Not valid altitude' ] + ifNotNil: [ :e | + AbstractAbsoluteCoordinatesPrinter default + printAltitude: e + on: aStream ] +] + +{ #category : #printing } +AbsoluteCoordinates >> printAltitudeString [ + + ^ String streamContents: [ :stream | self printAltitudeOn: stream ] +] + +{ #category : #printing } +AbsoluteCoordinates >> printLatitudeOn: aStream [ + + self latitude + ifNil: [ aStream nextPutAll: 'Not valid latitude' ] + ifNotNil: [ :e | + AbstractAbsoluteCoordinatesPrinter default + printLatitude: e + on: aStream ] +] + +{ #category : #printing } +AbsoluteCoordinates >> printLatitudeString [ + + ^ String streamContents: [ :stream | self printLatitudeOn: stream ] +] + +{ #category : #printing } +AbsoluteCoordinates >> printLongitudeOn: aStream [ + + self longitude + ifNil: [ aStream nextPutAll: 'Not valid longitude' ] + ifNotNil: [ :e | + AbstractAbsoluteCoordinatesPrinter default + printLongitude: e + on: aStream ] +] + +{ #category : #printing } +AbsoluteCoordinates >> printLongitudeString [ + + ^ String streamContents: [ :stream | self printLongitudeOn: stream ] +] + { #category : #printing } AbsoluteCoordinates >> printOn: aStream [ - super printOn: aStream. - aStream - nextPutAll: ' lat ', (self latitudeInDegrees ifNil:['--']) asString,'°'; - nextPutAll: ' lon ', (self longitudeInDegrees ifNil:['--']) asString,'°'; - nextPutAll: ' alt ', (self altitudeInMeters ifNil:['--']) asString,'m' + + self isValid + ifFalse: [ aStream nextPutAll: 'No valid coordinates' ] + ifTrue: [ + AbstractAbsoluteCoordinatesPrinter default + printAbsoluteCoordinates: self + on: aStream ] ] { #category : #accessing } diff --git a/src/GeoTools/AbstractAbsoluteCoordinatesPrinter.class.st b/src/GeoTools/AbstractAbsoluteCoordinatesPrinter.class.st new file mode 100644 index 0000000..bb7f703 --- /dev/null +++ b/src/GeoTools/AbstractAbsoluteCoordinatesPrinter.class.st @@ -0,0 +1,51 @@ +Class { + #name : #AbstractAbsoluteCoordinatesPrinter, + #superclass : #Object, + #classInstVars : [ + 'default' + ], + #category : #'GeoTools-Coordinates' +} + +{ #category : #cleanup } +AbstractAbsoluteCoordinatesPrinter class >> cleanUp [ + + super cleanUp. + default := nil +] + +{ #category : #accessing } +AbstractAbsoluteCoordinatesPrinter class >> default [ + + ^ default ifNil: [ default := DMSAbsoluteCoordinatesPrinter new ] +] + +{ #category : #testing } +AbstractAbsoluteCoordinatesPrinter class >> isAbstract [ + + ^ self == AbstractAbsoluteCoordinatesPrinter +] + +{ #category : #printing } +AbstractAbsoluteCoordinatesPrinter >> printAbsoluteCoordinates: anAbsoluteCoordinates on: aStream [ + + self subclassResponsibility +] + +{ #category : #printing } +AbstractAbsoluteCoordinatesPrinter >> printAltitude: anAltitudeUnit on: aStream [ + + self subclassResponsibility +] + +{ #category : #printing } +AbstractAbsoluteCoordinatesPrinter >> printLatitude: aLatitudeUnit on: aStream [ + + self subclassResponsibility +] + +{ #category : #printing } +AbstractAbsoluteCoordinatesPrinter >> printLongitude: aLongitudeUnit on: aStream [ + + self subclassResponsibility +] diff --git a/src/GeoTools/DMSAbsoluteCoordinatesPrinter.class.st b/src/GeoTools/DMSAbsoluteCoordinatesPrinter.class.st new file mode 100644 index 0000000..5b56377 --- /dev/null +++ b/src/GeoTools/DMSAbsoluteCoordinatesPrinter.class.st @@ -0,0 +1,304 @@ +" +See https://en.wikipedia.org/wiki/Degree_(angle)#Subdivisions +and https://en.wikipedia.org/wiki/ISO_6709 +" +Class { + #name : #DMSAbsoluteCoordinatesPrinter, + #superclass : #AbstractAbsoluteCoordinatesPrinter, + #instVars : [ + 'characterDegree', + 'characterMinute', + 'characterSecond', + 'characterNorth', + 'characterSouth', + 'characterEast', + 'characterWest', + 'characterSeparatorLatLon', + 'characterSeparatorAlt', + 'altitudeUnit', + 'withSpaces' + ], + #category : #'GeoTools-Coordinates' +} + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> altitudeUnit [ + + ^ altitudeUnit ifNil: [ altitudeUnit := Unit meters ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> altitudeUnit: anObject [ + + altitudeUnit := anObject +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterDegree [ + + ^ characterDegree ifNil:[ characterDegree := Character value: 16rB0 ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterDegree: anObject [ + + characterDegree := anObject +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterEast [ + + ^ characterEast ifNil: [ characterEast := $E ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterEast: anObject [ + + characterEast := anObject +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterMinute [ + + ^ characterMinute ifNil:[ characterMinute := Character value: 16r27 ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterMinute: anObject [ + + characterMinute := anObject +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterNorth [ + + ^ characterNorth ifNil: [ characterNorth := $N ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterNorth: anObject [ + + characterNorth := anObject +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterSecond [ + + ^ characterSecond ifNil:[ characterSecond := Character value: 16r22 ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterSecond: anObject [ + + characterSecond := anObject +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterSeparatorAlt [ + + ^ characterSeparatorAlt ifNil: [ characterSeparatorAlt := Character null ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterSeparatorAlt: anObject [ + + characterSeparatorAlt := anObject +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterSeparatorLatLon [ + + ^ characterSeparatorLatLon ifNil: [ characterSeparatorLatLon := Character space ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterSeparatorLatLon: anObject [ + + characterSeparatorLatLon := anObject +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterSouth [ + + ^ characterSouth ifNil: [ characterSouth := $S ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterSouth: anObject [ + + characterSouth := anObject +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterWest [ + + ^ characterWest ifNil: [ characterWest := $W ] +] + +{ #category : #accessing } +DMSAbsoluteCoordinatesPrinter >> characterWest: anObject [ + + characterWest := anObject +] + +{ #category : #printing } +DMSAbsoluteCoordinatesPrinter >> printAbsoluteCoordinates: anAbsoluteCoordinates on: aStream [ + + anAbsoluteCoordinates isValid ifFalse:[ ^ self ]. + + self printLatitude: anAbsoluteCoordinates latitude on: aStream. + + self withSpaces ifTrue: [ aStream space ]. + aStream nextPut: self characterSeparatorLatLon. + self withSpaces ifTrue: [ aStream space ]. + + self printLongitude: anAbsoluteCoordinates longitude on: aStream. + + anAbsoluteCoordinates altitude ifNotNil: [ :e | + self characterSeparatorAlt = Character null + ifFalse:[ aStream nextPut: self characterSeparatorAlt ] + ifTrue:[ aStream space ]. + self withSpaces ifTrue: [ aStream space ]. + self printAltitude: e on: aStream ] +] + +{ #category : #printing } +DMSAbsoluteCoordinatesPrinter >> printAltitude: anAltitudeUnit on: aStream [ + + | altitude | + anAltitudeUnit ifNil:[ ^ self ]. + altitude := (anAltitudeUnit convertTo: self altitudeUnit) value. + + aStream nextPutAll: (altitude roundTo: 1 asInteger) printString. + aStream nextPutAll: self altitudeUnit abbreviation +] + +{ #category : #printing } +DMSAbsoluteCoordinatesPrinter >> printLatitude: aLatitudeUnit on: aStream [ + "Degree Minute Second Orientation : 10°00'00''N" + + | num degrees minutes seconds latitude | + aLatitudeUnit ifNil:[ ^ self ]. + latitude := (aLatitudeUnit convertTo: Unit deg) value. + + "conversion" + num := latitude abs. + degrees := num truncated. + num := num - degrees. + num := (num * 60.0 roundTo: 0.01) asFloat. + num = 60.00 ifTrue: [ + degrees := degrees + 1. + num := 0.0 ]. + minutes := num truncated. + num := num - minutes. + num := (num * 60.0 roundTo: 0.01) asFloat. + num = 60.00 ifTrue: [ + minutes := minutes + 1. + num := 0.0 ]. + seconds := num truncated. + + "print" + degrees < 10.0 ifTrue: [ aStream nextPut: $0 ]. + aStream nextPutAll: degrees printString. + aStream nextPut: self characterDegree. + self withSpaces ifTrue:[ aStream space ]. + + minutes < 10.0 ifTrue: [ aStream nextPut: $0 ]. + aStream nextPutAll: minutes printString. + aStream nextPut: self characterMinute. + self withSpaces ifTrue:[ aStream space ]. + + seconds < 10.0 ifTrue: [ aStream nextPut: $0 ]. + aStream nextPutAll: seconds printString. + aStream nextPut: self characterSecond. + self withSpaces ifTrue:[ aStream space ]. + + latitude < 0.0 + ifTrue: [ aStream nextPut: self characterSouth ] + ifFalse: [ aStream nextPut: self characterNorth ]. + +] + +{ #category : #printing } +DMSAbsoluteCoordinatesPrinter >> printLongitude: aLongitudeUnit on: aStream [ + "Degree Minute Second Orientation : 100°00'00''E" + + | num degrees valAngle minutes seconds longitude | + aLongitudeUnit ifNil: [ ^ self ]. + longitude := (aLongitudeUnit convertTo: Unit deg) value. + + "conversion" + valAngle := longitude > 180.0 + ifTrue: [ longitude - 360.0 ] + ifFalse: [ + longitude < -180.0 + ifTrue: [ longitude + 360.0 ] + ifFalse: [ longitude ] ]. + num := valAngle abs. + degrees := num truncated. + num := num - degrees. + num := (num * 60.0 roundTo: 0.01) asFloat. + num = 60.00 ifTrue: [ + degrees := degrees + 1. + num := 0.0 ]. + minutes := num truncated. + num := num - minutes. + num := (num * 60.0 roundTo: 0.01) asFloat. + num = 60.00 ifTrue: [ + minutes := minutes + 1. + num := 0.0 ]. + seconds := num truncated. + + "print" + degrees < 100.0 ifTrue: [ aStream nextPut: $0 ]. + degrees < 10.0 ifTrue: [ aStream nextPut: $0 ]. + aStream nextPutAll: degrees printString. + aStream nextPut: self characterDegree. + self withSpaces ifTrue: [ aStream space ]. + + minutes < 10.0 ifTrue: [ aStream nextPut: $0 ]. + aStream nextPutAll: minutes printString. + aStream nextPut: self characterMinute. + self withSpaces ifTrue: [ aStream space ]. + + seconds < 10.0 ifTrue: [ aStream nextPut: $0 ]. + aStream nextPutAll: seconds printString. + aStream nextPut: self characterSecond. + self withSpaces ifTrue: [ aStream space ]. + + valAngle < 0.0 + ifTrue: [ aStream nextPut: self characterWest ] + ifFalse: [ aStream nextPut: self characterEast ] +] + +{ #category : #format } +DMSAbsoluteCoordinatesPrinter >> reset [ + "Default values are ISO 6709" + + self withSpaces: nil. + self characterSeparatorLatLon: nil. + self characterSeparatorAlt: nil. + + self characterDegree: nil. + self characterMinute: nil. + self characterSecond: nil. + + self characterNorth: nil. + self characterSouth: nil. + self characterEast: nil. + self characterWest: nil. + + self altitudeUnit: nil. +] + +{ #category : #format } +DMSAbsoluteCoordinatesPrinter >> withSpaces [ + + ^ withSpaces ifNil: [ withSpaces := false ] +] + +{ #category : #format } +DMSAbsoluteCoordinatesPrinter >> withSpaces: anObject [ + + withSpaces := anObject +] diff --git a/src/GeoTools/GeodesicUtils.class.st b/src/GeoTools/GeodesicUtils.class.st index 10f3e74..514205b 100644 --- a/src/GeoTools/GeodesicUtils.class.st +++ b/src/GeoTools/GeodesicUtils.class.st @@ -13,8 +13,7 @@ Class { { #category : #utilities } GeodesicUtils class >> absoluteCoordinatesAlongGeodesicFrom: aFromAbsoluteCoordinate to: aToAbsoluteCoordinate atFraction: aFraction [ - "Return a point at fraction t (0 <= t <= 1) along the geodesic from 'from' to 'to'. - Uses Vincenty inverse to get initial azimuth and distance, then Vincenty direct." + "Find the position that corresponds to a fraction of t (0 <= t <= 1) of a geodesic that is defined by two positions" ^ self formulas absoluteCoordinatesAlongGeodesicFrom: aFromAbsoluteCoordinate @@ -22,37 +21,19 @@ GeodesicUtils class >> absoluteCoordinatesAlongGeodesicFrom: aFromAbsoluteCoordi atFraction: aFraction ] -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> absoluteCoordinatesFrom: anAbsoluteCoordinates distance: aDistanceInM azimuth: anAzimuthInDegrees [ - - self - deprecated: 'Deprecated method name' - transformWith: '`@rcv absoluteCoordinatesFrom: @anAbsoluteCoordinates distance: @aDistanceInM azimuth: @anAzimuthInDegrees' - -> '`@rcv approximateAbsoluteCoordinatesFrom: @anAbsoluteCoordinates distance: @aDistanceInM azimuth: @anAzimuthInDegrees'. - - ^ self - approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates - distance: aDistanceInM - azimuth: anAzimuthInDegrees -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> absoluteCoordinatesFrom: anAbsoluteCoordinates distance: aDistanceInM azimuthInRadians: anAzimuthInRadians [ - - self - deprecated: 'Deprecated method name' - transformWith: '`@rcv absoluteCoordinatesFrom: @anAbsoluteCoordinates distance: @aDistanceInM azimuthInRadians: @anAzimuthInRadians' - -> '`@rcv approximateAbsoluteCoordinatesFrom: @anAbsoluteCoordinates distance: @aDistanceInM azimuthInRadians: @anAzimuthInRadians'. +{ #category : #utilities } +GeodesicUtils class >> absoluteCoordinatesFrom: anAbsoluteCoordinates distance: aDistance azimuth: anAzimuth [ + "Return the position (AbsoluteCoordinates) from a starting coordinates, a distance and an angle as Unit instances" ^ self - approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates - distance: aDistanceInM - azimuthInRadians: anAzimuthInRadians + absoluteCoordinatesFrom: anAbsoluteCoordinates + distanceInMeters: (aDistance convertTo: Unit meter) value + azimuthInRadians: (anAzimuth convertTo: Unit radian) value ] { #category : #utilities } GeodesicUtils class >> absoluteCoordinatesFrom: anAbsoluteCoordinates distanceInMeters: aDistanceInM azimuthInRadians: anAzimuthInRadians [ - "default using Vincenty" + "Return the position (AbsoluteCoordinates) from a starting coordinates, a distance in meters and an angle in radians" ^ self formulas absoluteCoordinatesFrom: anAbsoluteCoordinates @@ -60,272 +41,24 @@ GeodesicUtils class >> absoluteCoordinatesFrom: anAbsoluteCoordinates distanceIn azimuthInRadians: anAzimuthInRadians ] -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> absoluteCoordinatesFrom: anAbsoluteCoordinates distanceInNM: aDistanceInNM azimuthInRadians: anAzimuthInRadians [ - - self - deprecated: 'Deprecated method name' - transformWith: '`@rcv absoluteCoordinatesFrom: @anAbsoluteCoordinates distanceInNM: @aDistanceInNM azimuthInRadians:: @anAzimuthInRadians' - -> '`@rcv approximateAbsoluteCoordinatesFrom: @anAbsoluteCoordinates distanceInNM: @aDistanceInNM azimuthInRadians: @anAzimuthInRadians'. - - ^ self - approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates - distanceInNM: aDistanceInNM - azimuthInRadians: anAzimuthInRadians -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> absoluteCoordinatesWithVincentyFrom: anAbsoluteCoordinates distanceInM: distance azimuthInRadians: azimuth [ - | a f b lat1 lon1 alpha1 sinAlpha1 cosAlpha1 u1 sinU1 cosU1 sigma1 sinAlpha cosSqAlpha uSq A B sigma sigmaPrev iterLimit cosSigma sinSigma lat2 deltaSigma C L lon2 lambda cos2SigmaM tmp | - - self deprecated:'user absoluteCoordinatesFrom: anAbsoluteCoordinates distanceInMeters: aDistanceInM azimuthInRadians: anAzimuthInRadians'. - - anAbsoluteCoordinates isValid ifFalse: [ ^ nil ]. - distance = 0 ifTrue: [ ^ anAbsoluteCoordinates copy ]. - - a := WGS84 semiMajorAxisInMeters. - f := WGS84 flattening. - b := a * (1 - f). - - lat1 := anAbsoluteCoordinates latitudeInRadians. - lon1 := anAbsoluteCoordinates longitudeInRadians. - alpha1 := azimuth. - sinAlpha1 := alpha1 sin. - cosAlpha1 := alpha1 cos. - - "Calcul latitude réduite U1" - u1 := ((1 - f) * (lat1 tan)) arcTan. - sinU1 := u1 sin. - cosU1 := u1 cos. - - Transcript - show: 'u1 (rad): ', u1 printString; cr; - show: 'sinU1: ', sinU1 printString; cr; - show: 'cosU1: ', cosU1 printString; cr. - - "sigma1" - sigma1 := ((u1 tan) / cosAlpha1) arcTan. "arcTan au lieu de arcTan2" - Transcript - show: 'sigma1 (rad): ', sigma1 printString; cr. - - sinAlpha := cosU1 * sinAlpha1. - cosSqAlpha := 1 - (sinAlpha squared). - - uSq := (cosSqAlpha * ((a squared) - (b squared))) / (b squared). - A := 1 + ((uSq / 16384) * (4096 + (uSq * (-768 + (uSq * (320 - (175 * uSq))))))). - B := (uSq / 1024) * (256 + (uSq * (-128 + (uSq * (74 - (47 * uSq)))))). - - sigma := distance / (b * A). - sigmaPrev := 0.0. - iterLimit := 100. - - [ ((sigma - sigmaPrev) abs > 1e-12) and: [ iterLimit > 0 ] ] whileTrue: [ - cos2SigmaM := ((2 * sigma1) + sigma) cos. - sinSigma := sigma sin. - cosSigma := sigma cos. - - deltaSigma := (B * sinSigma) * ( - (cos2SigmaM) + (((B) / 4) * ( - ((cosSigma) * (-1 + (2 * ((cos2SigmaM) squared)))) - - ((((B) / 6) * (cos2SigmaM)) * (-3 + (4 * ((sinSigma) squared))) * (-3 + (4 * ((cos2SigmaM) squared)))) - )) - ). - - sigmaPrev := sigma. - sigma := (distance / (b * A)) + deltaSigma. - iterLimit := iterLimit - 1. - - Transcript - show: 'sigma: ', sigma printString; cr. - ]. - - tmp := ((sinU1 * sinSigma) - (cosU1 * cosSigma * cosAlpha1)). - lat2 := ((sinU1 * cosSigma) + (cosU1 * sinSigma * cosAlpha1)) arcTan2: ((1 - f) * (((sinAlpha squared) + (tmp * tmp)) sqrt)). - lambda := (sinSigma * sinAlpha1) arcTan2: ((cosU1 * cosSigma) - (sinU1 * sinSigma * cosAlpha1)). - C := ((f / 16) * cosSqAlpha * (4 + (f * (4 - (3 * cosSqAlpha))))). - L := lambda - ((1 - C) * f * sinAlpha1 * (sigma + (C * sinSigma * (cos2SigmaM + (C * cosSigma * (-1 + (2 * ((cos2SigmaM) squared)))))))). - lon2 := (((lon1 + L + (3 * Float pi)) euclideanModulo: (2 * Float pi)) - Float pi). - - Transcript - show: 'lat2 (rad): ', lat2 printString; cr; - show: 'lon2 (rad): ', lon2 printString; cr. - - ^ AbsoluteCoordinates latitudeInRadians: lat2 longitudeInRadians: lon2 - - -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates distance: aDistanceInM azimuth: anAzimuthInDegrees [ - - self deprecated:'use formulas'. - - ^ self - approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates - distance: (aDistanceInM / 1000 / 1.852) - azimuthInRadians: anAzimuthInDegrees degreesToRadians -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates distance: aDistanceInM azimuthInRadians: anAzimuthInRadians [ - - self deprecated:'use formulas'. - - ^ self - approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates - distanceInNM: (aDistanceInM / 1000 / 1.852) - azimuthInRadians: anAzimuthInRadians -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates distanceInM: aDistanceInM azimuthInRadians: anAzimuthInRadians [ - "Approximates a geographic position (latitude, longitude) from a starting point, a distance (in meters), and an azimuth (in radians), assuming a spherical Earth with radius equal to the WGS84 semi-major axis." - - | r δ φ1 λ1 φ2 λ2 x y | - - self deprecated:'use formulas'. - anAbsoluteCoordinates isValid ifFalse:[ ^ nil ]. - - r := WGS84 semiMajorAxisInMeters. - δ := aDistanceInM / r. - - φ1 := anAbsoluteCoordinates latitudeInRadians. - λ1 := anAbsoluteCoordinates longitudeInRadians. - - φ2 := (φ1 sin * δ cos + (φ1 cos * δ sin * anAzimuthInRadians cos)) arcSin. - φ2 := (φ2 max: (Float halfPi negated)) min: Float halfPi. - - x := δ cos - (φ1 sin * φ2 sin). - y := anAzimuthInRadians sin * δ * φ1 cos. - - λ2 := λ1 + (y arcTan: x). - λ2 := ((λ2 + Float pi) \\ (2 * Float pi)) - Float pi. - - ^ AbsoluteCoordinates - latitudeInDegrees: φ2 radiansToDegrees - longitudeInDegrees: λ2 radiansToDegrees - altitudeInMeters: anAbsoluteCoordinates altitudeInMeters -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates distanceInNM: aDistanceInNM azimuthInRadians: anAzimuthInRadians [ - "Formule de transformation tirée du livre de traité de navigation, c'est pourquoi elle fonctionne avec des NM" - | absoluteCoordinates deltaLat latArr div deltaLong longArr | - - self deprecated:'use formulas'. - anAbsoluteCoordinates isValid ifFalse:[ ^ nil ]. - - deltaLat := anAzimuthInRadians cos * aDistanceInNM / 60.0. - latArr := anAbsoluteCoordinates latitudeInDegrees + deltaLat. - - div := ((latArr + anAbsoluteCoordinates latitudeInDegrees) degreesToRadians / 2.0) cos. - deltaLong := ((div = 0) - ifFalse:[(anAzimuthInRadians sin / (div) abs * aDistanceInNM / 60.0)] - ifTrue:[0]). - - longArr := anAbsoluteCoordinates longitudeInDegrees + deltaLong. - - absoluteCoordinates := AbsoluteCoordinates latitudeInDegrees: latArr longitudeInDegrees: longArr. - (absoluteCoordinates longitudeInDegrees < -360 or:[absoluteCoordinates longitudeInDegrees > 360]) ifTrue:[^AbsoluteCoordinates zero]. - (absoluteCoordinates latitudeInDegrees < -360 or:[absoluteCoordinates latitudeInDegrees > 360]) ifTrue:[^AbsoluteCoordinates zero]. - - ^ absoluteCoordinates -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> approximateProjectedRadiusInMCenter: anAbsoluteCoordinates radius: aDistanceInM azimuth: anAzimuthInDegrees projection: aMapProjection [ - "Estimates the radius in projected meters by projecting two geographic points—one at the center and one at a given distance and azimuth—into Cartesian coordinates, then measuring their planar distance." - - | cartesianCoordinates1 extPt cartesianCoordinates2 radiusInM | - self deprecated:'transfered into GeoView project => GeoViewProjectionUtils projectedCartesianRadiusFromCenter: anAbsoluteCoordinates radiusInMeters: aDistanceInM azimuthInDegrees: anAzimuthInDegrees projection: aMapProjection'. - cartesianCoordinates1 := aMapProjection projLatLonToCart: anAbsoluteCoordinates. - extPt := self approximateAbsoluteCoordinatesFrom: anAbsoluteCoordinates distance: aDistanceInM azimuth: anAzimuthInDegrees. - cartesianCoordinates2 := aMapProjection projLatLonToCart: extPt. +{ #category : #utilities } +GeodesicUtils class >> azimuthFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate [ + "Return an azimuth between two absolute coordinates as a Unit instance" - radiusInM := (cartesianCoordinates1 asPoint - cartesianCoordinates2 asPoint) r abs. - ^ radiusInM + ^ (self formulas + azimuthInRadiansFrom: startAbsoluteCoordinate + to: endAbsoluteCoordinate) radians ] { #category : #utilities } GeodesicUtils class >> azimuthInRadiansFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate [ + "Return an azimuth between two absolute coordinates as a Number in radians degrees" ^ self formulas azimuthInRadiansFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate ] -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> azimuthInRadiansWithVincentyPreciseFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate [ - "Compute azimut between two Geodesic (lat/long) coordinates and return azimuth in radians" - - | d5 d6 d7 d8 d9 d10 d11 d12 d14 d13 d15 d16 d17 d19 d20 d21 d22 d23 d24 d25 d26 d27 d28 break | - - self deprecated:'use azimuthInRadiansFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate'. - - (startAbsoluteCoordinate isValid not or:[endAbsoluteCoordinate isValid not]) ifTrue:[ ^ 0 ]. - - d5 := (startAbsoluteCoordinate latitudeInRadians tan - * WGS84 semiMinorAxisInMeters / WGS84 semiMajorAxisInMeters) - arcTan. - d6 := (endAbsoluteCoordinate latitudeInRadians tan - * WGS84 semiMinorAxisInMeters / WGS84 semiMajorAxisInMeters) - arcTan. - d7 := d5 cos. - d8 := d6 cos. - d9 := d5 sin. - d10 := d6 sin. - d27 := WGS84 flattening / 16. - d11 := endAbsoluteCoordinate longitudeInRadians - - startAbsoluteCoordinate longitudeInRadians. - d12 := d11. - d13 := d11. - d14 := d12 sin. - d15 := d12 cos. - d28 := 0. - break := false. - - [ d28 < 100 and: [ break not ] ] whileTrue: [ - d16 := d8 * d14. - d17 := d7 * d10 - (d9 * d8 * d15). - d20 := (d16 * d16 + (d17 * d17)) sqrt. - d21 := d9 * d10 + (d7 * d8 * d15). - " !!! Math.atan2(y,x) => (x,y) theta " - d22 := (d21 @ d20) theta. - d20 = 0 ifTrue: [ ^0 ]. - d23 := d7 * d8 * d14 / d20. - d24 := 1 - (d23 * d23). - d25 := d24 < 1e-14 - ifTrue: [ 0 ] - ifFalse: [ d21 - (2 * d9 * d10 / d24) ]. - d26 := d27 * d24 * (4 + (WGS84 flattening * (4 - (3 * d24)))). - d19 := d12. - d16 := d25 + (d26 * d21 * (-1 + (2 * d25 * d25))). - d17 := 1 - d26 * WGS84 flattening * d23 * (d22 + (d26 * d20 * d16)). - d12 := d13 + d17. - d14 := d12 sin. - d15 := d12 cos. - break := (d12 - d19) abs < 1e-10. - break ifFalse: [ d28 := d28 + 1 ] ]. - - d28 := (d7 * d10 - (d9 * d8 * d15) @ (d8 * d14)) theta. - ^ d28 negative - ifTrue: [ d28 + (2 * Float pi) ] - ifFalse: [ d28 ] -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> checkAngle: anAngleInRadians isBetween: aStartAngleInRadians and: anEndAngleInRadians [ - "check if anAngleInRad is between startAngle and endAngle. Deal with the 0 : - self checkAngle: 0 isBetween: 355 and: 5 => true - while (0 between: 355 and: 5) => false" - - self deprecated:'Use directly Number extension'. - - ^ anAngleInRadians - isAngleInRadiansBetween: aStartAngleInRadians - and: anEndAngleInRadians -] - { #category : #cleanup } GeodesicUtils class >> cleanUp [ @@ -334,65 +67,18 @@ GeodesicUtils class >> cleanUp [ super cleanUp ] -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> computeECEFXYZ: anOriginAbsoluteCoordinates fromLocalXYZ: aLocalCartesianCoordinates [ - - self deprecated:'use directly absolute coordinates converting'. - - ^ anOriginAbsoluteCoordinates localToECEFCartesianCoordinates: - aLocalCartesianCoordinates -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> computeECEFXYZFromLgLatAlt: anAbsoluteCoordinates [ - - self deprecated:'use directly absolute coordinates converting'. - - ^ anAbsoluteCoordinates asECEFCartesianCoordinates -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> computeLgLatAltFromECEFXYZ: aCartesianCoordinates [ - - self deprecated:'use directly cartesian coordinates converting'. - - ^ aCartesianCoordinates asECEFtoAbsoluteCoordinates -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> convertGeodesicToAzimuthInRadiansFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate [ - "Compute azimut between two Geodesic (lat/long) coordinates and return azimuth in radians" - - self - deprecated: 'Deprecated method name' - transformWith: - '`@rcv convertGeodesicToAzimuthInRadiansFrom: @startAbsoluteCoordinate to: @endAbsoluteCoordinate' - -> - '`@rcv azimuthInRadiansFrom: @startAbsoluteCoordinate to: @endAbsoluteCoordinate'. - - ^ self - azimuthInRadiansFrom: startAbsoluteCoordinate - to: endAbsoluteCoordinate -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> convertGeodesicToDistanceInMeterFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate [ - "Vincenty algorithm to compute distance between two Geodesic (lat/long) coordinates and return it in meter" - - self - deprecated: 'Deprecated method name' - transformWith: - '`@rcv convertGeodesicToDistanceInMeterFrom: @startAbsoluteCoordinate to: @endAbsoluteCoordinate' - -> - '`@rcv distanceInMetersFrom: @startAbsoluteCoordinate to: @endAbsoluteCoordinate'. +{ #category : #utilities } +GeodesicUtils class >> distanceFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate [ + "Return a distance between two absolute coordinates as a Unit instance" - ^ self - distanceInMetersFrom: startAbsoluteCoordinate - to: endAbsoluteCoordinate + ^ (self formulas + distanceInMetersFrom: startAbsoluteCoordinate + to: endAbsoluteCoordinate) meters ] { #category : #utilities } GeodesicUtils class >> distanceInMetersFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate [ + "Return a distance between two absolute coordinates as a Number in meters" ^ self formulas distanceInMetersFrom: startAbsoluteCoordinate @@ -408,6 +94,22 @@ GeodesicUtils class >> formulas [ { #category : #utilities } GeodesicUtils class >> isAzimuthTowardsAreaFrom: anAbsCoordOrigin azimuth: anAzimuthInDegree area: aListOfAbsoluteCoords [ + self + deprecated: 'Use isAzimuthTowardsAreaFrom: anAbsCoordOrigin azimuthInDegrees: anAzimuthInDegree area: aListOfAbsoluteCoords' + transformWith: + '`@receiver isAzimuthTowardsAreaFrom: `@anAbsCoordOrigin azimuth: `@anAzimuthInDegree area: `@aListOfAbsoluteCoords' + -> + '`@receiver isAzimuthTowardsAreaFrom: `@anAbsCoordOrigin azimuthInDegrees: `@anAzimuthInDegree area: `@aListOfAbsoluteCoords'. + + ^ self + isAzimuthTowardsAreaFrom: anAbsCoordOrigin + azimuthInDegrees: anAzimuthInDegree degreesToRadians + area: aListOfAbsoluteCoords +] + +{ #category : #utilities } +GeodesicUtils class >> isAzimuthTowardsAreaFrom: anAbsCoordOrigin azimuthInDegrees: anAzimuthInDegree area: aListOfAbsoluteCoords [ + ^ self isAzimuthTowardsAreaFrom: anAbsCoordOrigin azimuthInRadians: anAzimuthInDegree degreesToRadians @@ -449,46 +151,6 @@ GeodesicUtils class >> isAzimuthTowardsAreaFrom: anAbsCoordOrigin azimuthInRadia ^ isPointingArea ] -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> localPolar: aPolarCoordinates toGeodesicFrom: anOriginAbsoluteCoordinates [ - "Compute the geodesic position of a specified line end, knowing its azimuth, elevation, length and start geodesic position. Warning: that method doesn't take in account the earth curve as orthodromic2geodesic does. - But that method takes in account the altitude in the calculus." - - self deprecated:'Use polar coordinates converting'. - - ^ aPolarCoordinates localToAbsoluteCoordinates: - anOriginAbsoluteCoordinates -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> preciseConvertGeodesicToAzimuthInRadiansFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate [ - "Compute azimut between two Geodesic (lat/long) coordinates and return azimuth in radians" - - self - deprecated: 'Deprecated method name' - transformWith: - '`@rcv preciseConvertGeodesicToAzimuthInRadiansFrom: @startAbsoluteCoordinate to: @endAbsoluteCoordinate' - -> - '`@rcv azimuthInRadiansWithVincentyPreciseFrom: @startAbsoluteCoordinate to: @endAbsoluteCoordinate'. - - ^ self azimuthInRadiansWithVincentyPreciseFrom: startAbsoluteCoordinate to: endAbsoluteCoordinate -] - -{ #category : #'to remove as soon as possible' } -GeodesicUtils class >> projectedRadiusInMCenter: anAbsoluteCoordinates radius: aDistanceInM azimuth: anAzimuthInDegrees projection: aMapProjection [ - - self - deprecated: 'Deprecated method name' - transformWith: '`@rcv projectedRadiusInMCenter: @anAbsoluteCoordinates radius: @aDistanceInM azimuth: @anAzimuthInDegrees projection: @aMapProjection' - -> '`@rcv approximateProjectedRadiusInMCenter: @anAbsoluteCoordinates radius: @aDistanceInM azimuth: @anAzimuthInDegrees projection: @aMapProjection'. - - ^ self - approximateProjectedRadiusInMCenter: anAbsoluteCoordinates - radius: aDistanceInM - azimuth: anAzimuthInDegrees - projection: aMapProjection -] - { #category : #'see class side' } GeodesicUtils >> seeClassSide [ ]