@@ -232,6 +232,7 @@ protected function transformFeature(array $feature): MobileNoteData {
232232 // Convert geometry to GeoJSON object.
233233 if (!empty ($ geometry ['coordinates ' ])) {
234234 $ item ['geometry ' ] = $ this ->convertGeometry ($ geometry );
235+ $ item ['map_url ' ] = $ this ->buildMapUrl ($ geometry ['coordinates ' ]);
235236 }
236237
237238 $ dataDefinition = $ this ->typedDataManager ->createDataDefinition ('mobilenote_data ' );
@@ -310,4 +311,66 @@ protected function convertGeometry(array $geometry): object {
310311 ];
311312 }
312313
314+ /**
315+ * Builds a kartta.hel.fi map URL from EPSG:3879 coordinates.
316+ *
317+ * Buffers the LineString into a Polygon (10m) and generates a WKT-based URL.
318+ *
319+ * @param array $coordinates
320+ * Array of [x, y] coordinate pairs in EPSG:3879.
321+ *
322+ * @return string
323+ * The kartta.hel.fi URL.
324+ */
325+ protected function buildMapUrl (array $ coordinates ): string {
326+ $ buffer = 10 ;
327+
328+ // Build perpendicular offset polygon from the LineString.
329+ $ left = [];
330+ $ right = [];
331+ $ count = count ($ coordinates );
332+
333+ for ($ i = 0 ; $ i < $ count - 1 ; $ i ++) {
334+ $ dx = $ coordinates [$ i + 1 ][0 ] - $ coordinates [$ i ][0 ];
335+ $ dy = $ coordinates [$ i + 1 ][1 ] - $ coordinates [$ i ][1 ];
336+ $ len = sqrt ($ dx * $ dx + $ dy * $ dy );
337+ if ($ len == 0 ) {
338+ continue ;
339+ }
340+ // Perpendicular unit vector.
341+ $ nx = -$ dy / $ len * $ buffer ;
342+ $ ny = $ dx / $ len * $ buffer ;
343+
344+ $ left [] = [round ($ coordinates [$ i ][0 ] + $ nx , 2 ), round ($ coordinates [$ i ][1 ] + $ ny , 2 )];
345+ $ left [] = [round ($ coordinates [$ i + 1 ][0 ] + $ nx , 2 ), round ($ coordinates [$ i + 1 ][1 ] + $ ny , 2 )];
346+ $ right [] = [round ($ coordinates [$ i ][0 ] - $ nx , 2 ), round ($ coordinates [$ i ][1 ] - $ ny , 2 )];
347+ $ right [] = [round ($ coordinates [$ i + 1 ][0 ] - $ nx , 2 ), round ($ coordinates [$ i + 1 ][1 ] + $ ny , 2 )];
348+ }
349+
350+ // Close the polygon: left side forward, right side reversed.
351+ $ ring = array_merge ($ left , array_reverse ($ right ));
352+ $ ring [] = $ ring [0 ];
353+
354+ // Build WKT.
355+ $ points = array_map (fn ($ p ) => $ p [0 ] . ' ' . $ p [1 ], $ ring );
356+ $ wkt = 'POLYGON (( ' . implode (', ' , $ points ) . ')) ' ;
357+
358+ // Calculate center point.
359+ $ sumX = $ sumY = 0 ;
360+ foreach ($ coordinates as $ coord ) {
361+ $ sumX += $ coord [0 ];
362+ $ sumY += $ coord [1 ];
363+ }
364+ $ centerE = round ($ sumX / $ count );
365+ $ centerN = round ($ sumY / $ count );
366+
367+ // Build URL. rawurlencode uses %20 for spaces (required by kartta.hel.fi).
368+ return sprintf (
369+ 'https://kartta.hel.fi/?e=%d&n=%d&r=2&l=Karttasarja&geom=%s ' ,
370+ $ centerE ,
371+ $ centerN ,
372+ rawurlencode ($ wkt )
373+ );
374+ }
375+
313376}
0 commit comments