From 158f022f88a61be1a27245567a292c45154ca0e4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Thu, 21 Nov 2024 10:46:00 +0100
Subject: [PATCH] feat(vector-map): scale element dashed border

---
 .../utils/shapes/elements/BaseMultiPolygon.ts | 23 +++++++++++--------
 .../utils/shapes/layer/Layer.ts               | 13 ++++-------
 .../utils/shapes/reaction/Reaction.ts         | 11 ++++-----
 .../shapes/style/getScaledElementStyle.ts     | 17 ++++++++++++++
 4 files changed, 40 insertions(+), 24 deletions(-)
 create mode 100644 src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.ts

diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts
index b53e6ee6..5997a743 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts
@@ -166,7 +166,7 @@ export default abstract class BaseMultiPolygon {
   protected drawMultiPolygonFeature(mapInstance: MapInstance): void {
     this.feature = new Feature({
       geometry: new MultiPolygon(this.polygons),
-      getTextScale: (resolution: number): number => {
+      getScale: (resolution: number): number => {
         const maxZoom = mapInstance?.getView().get('originalMaxZoom');
         if (maxZoom) {
           const minResolution = mapInstance?.getView().getResolutionForZoom(maxZoom);
@@ -185,10 +185,10 @@ export default abstract class BaseMultiPolygon {
 
   protected getStyle(feature: FeatureLike, resolution: number): Style | Array<Style> | void {
     const styles: Array<Style> = [];
-    const getTextScale = feature.get('getTextScale');
-    let textScale = 1;
-    if (getTextScale instanceof Function) {
-      textScale = getTextScale(resolution);
+    const getScale = feature.get('getScale');
+    let scale = 1;
+    if (getScale instanceof Function) {
+      scale = getScale(resolution);
     }
 
     let type: string;
@@ -206,7 +206,7 @@ export default abstract class BaseMultiPolygon {
       }
       if (
         [MAP_ELEMENT_TYPES.MODIFICATION, MAP_ELEMENT_TYPES.TEXT].includes(type) &&
-        textScale * fontSize <= 4
+        scale * fontSize <= 4
       ) {
         return;
       }
@@ -215,14 +215,19 @@ export default abstract class BaseMultiPolygon {
       const textStyle = clonedStyle.getText();
       const strokeStyle = clonedStyle.getStroke();
       if (type === 'text' && textStyle) {
-        textStyle.setScale(textScale);
+        textStyle.setScale(scale);
         textStyle.setText(text);
       }
       if (strokeStyle && lineWidth) {
-        if (lineWidth * textScale < 0.08 && this.sboTerm !== COMPLEX_SBO_TERM) {
+        if (lineWidth * scale < 0.08 && this.sboTerm !== COMPLEX_SBO_TERM) {
           clonedStyle.setStroke(null);
         } else {
-          strokeStyle.setWidth(lineWidth * textScale);
+          strokeStyle.setWidth(lineWidth * scale);
+          const lineDash = strokeStyle.getLineDash();
+          if (lineDash) {
+            const newLineDash = lineDash.map(width => width * scale);
+            strokeStyle.setLineDash(newLineDash);
+          }
         }
       }
       styles.push(clonedStyle);
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.ts
index dd8b81dc..9a91384f 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.ts
@@ -20,6 +20,7 @@ import { FeatureLike } from 'ol/Feature';
 import Style from 'ol/style/Style';
 import { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types';
 import { LAYER_ELEMENT_TYPES } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
+import getScaledElementStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle';
 
 export interface LayerProps {
   texts: Array<LayerText>;
@@ -298,23 +299,19 @@ export default class Layer {
     }
 
     const scale = minResolution / resolution;
-    const lineWidth = feature.get('lineWidth') * scale;
+    const lineWidth = feature.get('lineWidth');
     const type = feature.get('elementType');
 
     if (type === LAYER_ELEMENT_TYPES.ARROW && scale <= 0.08) {
       return [];
     }
-    let clonedStyle: Style;
+
     if (style instanceof Style) {
-      clonedStyle = style.clone();
-      clonedStyle.getStroke()?.setWidth(lineWidth);
-      styles.push(clonedStyle);
+      styles.push(getScaledElementStyle(style, lineWidth, scale));
     } else if (Array.isArray(style)) {
       style.forEach(singleStyle => {
         if (singleStyle instanceof Style) {
-          clonedStyle = singleStyle.clone();
-          clonedStyle.getStroke()?.setWidth(lineWidth);
-          styles.push(clonedStyle);
+          styles.push(getScaledElementStyle(singleStyle, lineWidth, scale));
         }
       });
     }
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts
index c4fc7499..f8140764 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts
@@ -19,6 +19,7 @@ import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shape
 import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex';
 import { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types';
 import { FEATURE_TYPE } from '@/constants/features';
+import getScaledElementStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle';
 
 export interface ReactionProps {
   id: number;
@@ -332,7 +333,7 @@ export default class Reaction {
     }
 
     const scale = minResolution / resolution;
-    const lineWidth = feature.get('lineWidth') * scale;
+    const lineWidth = feature.get('lineWidth');
     const type = feature.get('elementType');
     const fontSize = feature.get('fontSize');
 
@@ -344,15 +345,11 @@ export default class Reaction {
     }
 
     if (style instanceof Style) {
-      style.getStroke()?.setWidth(lineWidth);
-      style.getText()?.setScale(scale);
-      styles.push(style);
+      styles.push(getScaledElementStyle(style, lineWidth, scale));
     } else if (Array.isArray(style)) {
       style.forEach(singleStyle => {
         if (singleStyle instanceof Style) {
-          singleStyle.getStroke()?.setWidth(lineWidth);
-          singleStyle.getText()?.setScale(scale);
-          styles.push(singleStyle);
+          styles.push(getScaledElementStyle(singleStyle, lineWidth, scale));
         }
       });
     }
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.ts
new file mode 100644
index 00000000..f4a4f77a
--- /dev/null
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle.ts
@@ -0,0 +1,17 @@
+import Style from 'ol/style/Style';
+
+export default function getScaledElementStyle(
+  style: Style,
+  lineWidth: number,
+  scale: number,
+): Style {
+  const clonedStyle = style.clone();
+  const lineDash = clonedStyle.getStroke()?.getLineDash();
+  if (lineDash) {
+    const newLineDash = lineDash.map(width => width * scale);
+    clonedStyle.getStroke()?.setLineDash(newLineDash);
+  }
+  clonedStyle.getStroke()?.setWidth(lineWidth * scale);
+  clonedStyle.getText()?.setScale(scale);
+  return clonedStyle;
+}
-- 
GitLab