@@ -28,11 +28,12 @@ function Spherize([lon, lat] : [number, number]){
2828}
2929
3030function Borders ( { features} :{ features : any } ) {
31- const { xRange, yRange, plotType, borderColor, lonExtent, latExtent, lonResolution, latResolution} = usePlotStore ( useShallow ( state => ( {
31+ const { xRange, yRange, plotType, borderColor, lonExtent, latExtent, lonResolution, latResolution, is360Deg } = usePlotStore ( useShallow ( state => ( {
3232 xRange : state . xRange , yRange : state . yRange ,
3333 plotType : state . plotType , borderColor : state . borderColor ,
3434 lonExtent : state . lonExtent , latExtent : state . latExtent ,
3535 lonResolution : state . lonResolution , latResolution : state . latResolution ,
36+ is360Deg :state . is360Deg
3637 } ) ) )
3738 const { flipY, shape } = useGlobalStore ( useShallow ( state => ( {
3839 flipY : state . flipY ,
@@ -90,93 +91,105 @@ function Borders({features}:{features: any}){
9091 const lines = [ ] ;
9192
9293 if ( feature . geometry . type === 'LineString' ) {
93- const points : THREE . Vector3 [ ] = [ ] ;
94- feature . geometry . coordinates . forEach ( ( [ lon , lat ] : [ number , number ] ) => {
95- const [ x , y , z ] = spherize
96- ? Spherize ( [ - lon , lat ] )
97- : Reproject ( [ lon , lat ] , lonBounds , latBounds ) ;
98- points . push ( new THREE . Vector3 ( x , y , z ) ) ;
99- } ) ;
100- const positions = new Float32Array ( points . length * 3 ) ;
101- points . forEach ( ( point , i ) => {
102- positions . set ( [ point . x , point . y , point . z ] , i * 3 ) ;
103- } ) ;
104-
105- const geometry = new THREE . BufferGeometry ( ) ;
106- geometry . setAttribute ( 'position' , new THREE . BufferAttribute ( positions , 3 ) ) ;
107-
108- lines . push (
109- geometry
110- ) ;
111- }
112-
113- else if ( feature . geometry . type === 'MultiPolygon' ) {
114- const islands = feature . geometry . coordinates ;
115- islands . forEach ( ( island : number [ ] [ ] [ ] , idx : number ) => {
116- let thisIdx = idx ;
117- const ring = island [ 0 ] ; // outer ring
118- const islandPoints : THREE . Vector3 [ ] = [ ] ;
119- ring . forEach ( ( [ lon , lat ] ) => {
120- thisIdx ++ ;
121- const [ x , y , z ] = spherize
122- ? Spherize ( [ - lon , lat ] )
123- : Reproject ( [ lon , lat ] , lonBounds , latBounds ) ;
124- islandPoints . push ( new THREE . Vector3 ( x , y , z ) ) ;
125- } ) ;
126- const positions = new Float32Array ( islandPoints . length * 3 ) ;
127- islandPoints . forEach ( ( point , i ) => {
128- positions . set ( [ point . x , point . y , point . z ] , i * 3 ) ;
129- } ) ;
130- const geometry = new THREE . BufferGeometry ( ) ;
131- geometry . setAttribute ( 'position' , new THREE . BufferAttribute ( positions , 3 ) ) ;
132- lines . push (
133- geometry
134- ) ;
135- } ) ;
136- }
137- else {
138- const polygons =
139- feature . geometry . type === 'Polygon'
140- ? [ feature . geometry . coordinates ]
141- : feature . geometry . coordinates ;
142-
143- polygons . forEach ( ( polygon : number [ ] [ ] [ ] ) => {
14494 const points : THREE . Vector3 [ ] = [ ] ;
145- polygon . forEach ( ( ring : number [ ] [ ] ) => {
146- ring . forEach ( ( [ lon , lat ] ) => {
95+ feature . geometry . coordinates . forEach ( ( [ lon , lat ] : [ number , number ] ) => {
14796 const [ x , y , z ] = spherize
14897 ? Spherize ( [ - lon , lat ] )
14998 : Reproject ( [ lon , lat ] , lonBounds , latBounds ) ;
15099 points . push ( new THREE . Vector3 ( x , y , z ) ) ;
151100 } ) ;
152- } ) ;
153101 const positions = new Float32Array ( points . length * 3 ) ;
154102 points . forEach ( ( point , i ) => {
155103 positions . set ( [ point . x , point . y , point . z ] , i * 3 ) ;
156104 } ) ;
157105 const geometry = new THREE . BufferGeometry ( ) ;
158106 geometry . setAttribute ( 'position' , new THREE . BufferAttribute ( positions , 3 ) ) ;
159- lines . push (
160- geometry
161- ) ;
162- } ) ;
107+ lines . push ( geometry ) ;
108+ }
109+ else if ( feature . geometry . type === 'MultiPolygon' ) {
110+ const islands = feature . geometry . coordinates ;
111+ islands . forEach ( ( island : number [ ] [ ] [ ] , idx : number ) => {
112+ let thisIdx = idx ;
113+ const ring = island [ 0 ] ; // outer ring
114+ const islandPoints : THREE . Vector3 [ ] = [ ] ;
115+ ring . forEach ( ( [ lon , lat ] ) => {
116+ thisIdx ++ ;
117+ const [ x , y , z ] = spherize
118+ ? Spherize ( [ - lon , lat ] )
119+ : Reproject ( [ lon , lat ] , lonBounds , latBounds ) ;
120+ islandPoints . push ( new THREE . Vector3 ( x , y , z ) ) ;
121+ } ) ;
122+ const positions = new Float32Array ( islandPoints . length * 3 ) ;
123+ islandPoints . forEach ( ( point , i ) => {
124+ positions . set ( [ point . x , point . y , point . z ] , i * 3 ) ;
125+ } ) ;
126+ const geometry = new THREE . BufferGeometry ( ) ;
127+ geometry . setAttribute ( 'position' , new THREE . BufferAttribute ( positions , 3 ) ) ;
128+ lines . push ( geometry ) ;
129+ } ) ;
130+ }
131+ else {
132+ const polygons =
133+ feature . geometry . type === 'Polygon'
134+ ? [ feature . geometry . coordinates ]
135+ : feature . geometry . coordinates ;
136+
137+ polygons . forEach ( ( polygon : number [ ] [ ] [ ] ) => {
138+ const points : THREE . Vector3 [ ] = [ ] ;
139+ polygon . forEach ( ( ring : number [ ] [ ] ) => {
140+ ring . forEach ( ( [ lon , lat ] ) => {
141+ const [ x , y , z ] = spherize
142+ ? Spherize ( [ - lon , lat ] )
143+ : Reproject ( [ lon , lat ] , lonBounds , latBounds ) ;
144+ points . push ( new THREE . Vector3 ( x , y , z ) ) ;
145+ } ) ;
146+ } ) ;
147+ const positions = new Float32Array ( points . length * 3 ) ;
148+ points . forEach ( ( point , i ) => {
149+ positions . set ( [ point . x , point . y , point . z ] , i * 3 ) ;
150+ } ) ;
151+ const geometry = new THREE . BufferGeometry ( ) ;
152+ geometry . setAttribute ( 'position' , new THREE . BufferAttribute ( positions , 3 ) ) ;
153+ lines . push ( geometry ) ;
154+ } ) ;
163155 }
164156 return lines ;
165157 } ) ;
166158 } , [ features , spherize , flipY , lonBounds , latBounds ] ) ;
167159
160+
168161 const lines = useMemo ( ( ) => {
169- return lineGeometries . map ( ( geom : THREE . BufferGeometry , idx : number ) => {
170- const line = new THREE . Line ( geom , lineShaderMat ) ;
171- return < primitive key = { `border-${ idx } ` } object = { line } /> ;
162+ const results : any [ ] = [ ]
163+ lineGeometries . map ( ( geom : THREE . BufferGeometry , idx : number ) => {
164+ if ( is360Deg && ! spherize ) {
165+ const wrappedGeom = geom . clone ( )
166+ const { count, array} = geom . attributes . position
167+ for ( let i = 0 ; i < count ; i ++ ) {
168+ const idx = i * 3 ;
169+ array [ idx ] = array [ idx ] + 0.5
170+ }
171+ const wrappedArray = wrappedGeom . attributes . position . array
172+ for ( let i = 0 ; i < count ; i ++ ) {
173+ const idx = i * 3 ;
174+ wrappedArray [ idx ] = wrappedArray [ idx ] - 1
175+ }
176+ const line = new THREE . Line ( geom , lineShaderMat ) ;
177+ const wrappedLine = new THREE . Line ( wrappedGeom , lineShaderMat ) ;
178+ results . push ( < primitive key = { `border-${ idx } ` } object = { line } /> )
179+ results . push ( < primitive key = { `border-${ idx } _wrap` } object = { wrappedLine } /> )
180+ } else {
181+ const line = new THREE . Line ( geom , lineShaderMat ) ;
182+ results . push ( < primitive key = { `border-${ idx } ` } object = { line } /> ) ;
183+ }
172184 } ) ;
185+ return results
173186 } , [ lineGeometries , lineShaderMat ] ) ;
174187
175188 return (
176- < >
177- { lines }
178- </ >
179- )
189+ < >
190+ { lines }
191+ </ >
192+ )
180193}
181194const CountryBorders = ( ) => {
182195 const [ coastLines , setCoastLines ] = useState < any > ( null )
@@ -187,10 +200,11 @@ const CountryBorders = () => {
187200 dataShape : state . dataShape ,
188201 is4D : state . is4D
189202 } ) ) )
190- const { zRange, plotType, showBorders, timeScale, rotateFlat, pointSize} = usePlotStore ( useShallow ( state => ( {
203+ const { zRange, plotType, showBorders, timeScale, rotateFlat, pointSize, is360Deg } = usePlotStore ( useShallow ( state => ( {
191204 zRange : state . zRange , plotType : state . plotType ,
192205 showBorders : state . showBorders , timeScale : state . timeScale ,
193- rotateFlat : state . rotateFlat , pointSize :state . pointSize
206+ rotateFlat : state . rotateFlat , pointSize :state . pointSize ,
207+ is360Deg : state . is360Deg
194208 } ) ) )
195209 const { analysisMode, axis} = useAnalysisStore ( useShallow ( state => ( {
196210 analysisMode : state . analysisMode ,
@@ -245,6 +259,7 @@ const CountryBorders = () => {
245259 < group
246260 visible = { showBorders && ! ( analysisMode && axis != 0 ) }
247261 position = { ( spherize || isFlatMap ) ? [ 0 , 0 , ( isFlatMap ? 0.001 : 0 ) ] : [ 0 , 0 , swapSides ? zRange [ 0 ] * ( isPC ? depthScale + pointSize / 10000 : timeRatio / 2 ) : zRange [ 1 ] * ( isPC ? depthScale + pointSize / 10000 : timeRatio / 2 ) ] } // I don't know what value to use here. THis seems okay but not perfect
262+ rotation = { [ 0 , ( is360Deg && spherize ) ? Math . PI : 0 , 0 ] }
248263 >
249264 { coastLines && < Borders features = { coastLines } /> }
250265 { borders && < Borders features = { borders } /> }
0 commit comments