From 14f5a91fc084943d14688185969165e4d3aca420 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Wed, 11 Dec 2024 13:35:09 +0100
Subject: [PATCH 1/4] feat(vector-map): add duration to mouseWheelZoom

---
 .../utils/config/reactionsLayer/useOlMapReactionsLayer.ts       | 2 ++
 src/components/Map/MapViewer/utils/useOlMap.ts                  | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts b/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
index bf0d3389..86787f11 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
@@ -244,6 +244,8 @@ export const useOlMapReactionsLayer = ({
   return useMemo(() => {
     const vectorLayer = new VectorLayer({
       source: vectorSource,
+      updateWhileAnimating: true,
+      updateWhileInteracting: true,
     });
     vectorLayer.set('type', VECTOR_MAP_LAYER_TYPE);
     return vectorLayer;
diff --git a/src/components/Map/MapViewer/utils/useOlMap.ts b/src/components/Map/MapViewer/utils/useOlMap.ts
index 23d585e0..68ec65bd 100644
--- a/src/components/Map/MapViewer/utils/useOlMap.ts
+++ b/src/components/Map/MapViewer/utils/useOlMap.ts
@@ -65,7 +65,7 @@ export const useOlMap: UseOlMap = ({ target } = {}) => {
         mouseWheelZoom: false,
       }).extend([
         new MouseWheelZoom({
-          duration: 0,
+          duration: 250,
           timeout: 80,
         }),
       ]),
-- 
GitLab


From 7d8aec25002cdac1856dad1a48af5bb303ee6a54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Wed, 11 Dec 2024 13:38:19 +0100
Subject: [PATCH 2/4] bugfix(vector-map): add overlaysOrder state in
 useOlMapReactionsLayer to avoid elements reloading

---
 .../reactionsLayer/useOlMapReactionsLayer.ts  | 19 +++++++++---
 .../utils/shapes/elements/BaseMultiPolygon.ts |  2 +-
 .../shapes/overlay/areOverlayOrdersEqual.ts   | 31 +++++++++++++++++++
 3 files changed, 46 insertions(+), 6 deletions(-)
 create mode 100644 src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/areOverlayOrdersEqual.ts

diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts b/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
index 86787f11..509d5cbb 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts
@@ -2,7 +2,7 @@
 import { Feature } from 'ol';
 import VectorLayer from 'ol/layer/Vector';
 import VectorSource from 'ol/source/Vector';
-import { useEffect, useMemo } from 'react';
+import { useEffect, useMemo, useState } from 'react';
 import { usePointToProjection } from '@/utils/map/usePointToProjection';
 import MapElement from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement';
 import { useSelector } from 'react-redux';
@@ -48,6 +48,8 @@ import { mapBackgroundTypeSelector, mapDataSizeSelector } from '@/redux/map/map.
 import MapBackgroundsEnum from '@/redux/map/map.enums';
 import { setMapBackgroundType } from '@/redux/map/map.slice';
 import { ZOOM_RESCALING_FACTOR } from '@/constants/map';
+import { OverlayOrder } from '@/redux/overlayBioEntity/overlayBioEntity.utils';
+import areOverlayOrdersEqual from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/areOverlayOrdersEqual';
 
 export const useOlMapReactionsLayer = ({
   mapInstance,
@@ -56,6 +58,7 @@ export const useOlMapReactionsLayer = ({
 }): VectorLayer<VectorSource<Feature>> => {
   const dispatch = useAppDispatch();
 
+  const [overlaysOrderState, setOverlaysOrderState] = useState<Array<OverlayOrder>>([]);
   const currentModelId = useSelector(currentModelIdSelector);
   const shapes = useSelector(bioShapesSelector);
   const mapSize = useSelector(mapDataSizeSelector);
@@ -84,6 +87,12 @@ export const useOlMapReactionsLayer = ({
     return mapSize.maxZoom * ZOOM_RESCALING_FACTOR === mapModelOriginalMaxZoom;
   }, [mapModelOriginalMaxZoom, mapSize.maxZoom]);
 
+  useEffect(() => {
+    if (areOverlayOrdersEqual(overlaysOrderState, overlaysOrder)) {
+      setOverlaysOrderState(overlaysOrder);
+    }
+  }, [overlaysOrder, overlaysOrderState]);
+
   useEffect(() => {
     if (!currentModelId) {
       return;
@@ -97,10 +106,10 @@ export const useOlMapReactionsLayer = ({
   }, [currentModelId, dispatch, reactionsLoading, modelElementsLoading]);
 
   useEffect(() => {
-    if (overlaysOrder.length) {
+    if (overlaysOrderState.length) {
       dispatch(setMapBackgroundType(MapBackgroundsEnum.NETWORK));
     }
-  }, [dispatch, overlaysOrder]);
+  }, [dispatch, overlaysOrderState]);
 
   const groupedElementsOverlays = useMemo(() => {
     const elementsBioEntitesOverlay = debouncedBioEntities.filter(
@@ -202,7 +211,7 @@ export const useOlMapReactionsLayer = ({
       shapes,
       lineTypes,
       groupedElementsOverlays,
-      overlaysOrder,
+      overlaysOrderState,
       getOverlayBioEntityColorByAvailableProperties,
       vectorSource,
       mapInstance,
@@ -216,7 +225,7 @@ export const useOlMapReactionsLayer = ({
     isCorrectMapInstanceViewScale,
     lineTypes,
     groupedElementsOverlays,
-    overlaysOrder,
+    overlaysOrderState,
     getOverlayBioEntityColorByAvailableProperties,
     vectorSource,
     mapInstance,
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 c13c61f4..30f48a79 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts
@@ -309,7 +309,7 @@ export default abstract class BaseMultiPolygon {
               largestExtent,
               this.text,
               scale,
-              this.zIndex + 1000,
+              this.zIndex + 100000,
               this.mapSize,
             ),
           );
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/areOverlayOrdersEqual.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/areOverlayOrdersEqual.ts
new file mode 100644
index 00000000..965ef019
--- /dev/null
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/overlay/areOverlayOrdersEqual.ts
@@ -0,0 +1,31 @@
+/* eslint-disable no-magic-numbers */
+import { OverlayOrder } from '@/redux/overlayBioEntity/overlayBioEntity.utils';
+
+export default function areOverlayOrdersEqual(
+  overlaysOrder1: Array<OverlayOrder>,
+  overlaysOrder2: Array<OverlayOrder>,
+): boolean {
+  if (overlaysOrder1 === overlaysOrder2) {
+    return true;
+  }
+
+  if (overlaysOrder1.length !== overlaysOrder2.length) {
+    return false;
+  }
+
+  for (let index = 0; index < overlaysOrder1.length; index += 1) {
+    const obj1 = overlaysOrder1[index];
+    const obj2 = overlaysOrder2[index];
+
+    if (
+      obj1.id !== obj2.id ||
+      obj1.order !== obj2.order ||
+      obj1.calculatedOrder !== obj2.calculatedOrder ||
+      obj1.index !== obj2.index
+    ) {
+      return false;
+    }
+  }
+
+  return true;
+}
-- 
GitLab


From 20bd0d613a953091ecf1ec3e23870dd68001dd48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Wed, 11 Dec 2024 14:46:42 +0100
Subject: [PATCH 3/4] feat(vector-map): add semantic view as a default and stop
 masking content of elemenets when text labels appear

---
 .../utils/shapes/elements/BaseMultiPolygon.ts | 15 ++---------
 .../utils/shapes/elements/MapElement.ts       |  3 ---
 .../elements/handleSemanticView.test.ts       | 27 +++++--------------
 .../shapes/elements/handleSemanticView.ts     |  3 +--
 .../utils/shapes/reaction/Reaction.ts         |  3 +--
 src/redux/map/map.constants.ts                |  2 +-
 6 files changed, 12 insertions(+), 41 deletions(-)

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 30f48a79..fd2f74fd 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts
@@ -196,8 +196,6 @@ export default abstract class BaseMultiPolygon {
       });
       const textPolygon = new Polygon([[textCoords, textCoords]]);
       textPolygon.set('type', MAP_ELEMENT_TYPES.TEXT);
-      textPolygon.set('text', this.text);
-      textPolygon.set('fontSize', this.fontSize);
       const textStyle = getTextStyle({
         text: this.text,
         fontSize: this.fontSize,
@@ -267,12 +265,11 @@ export default abstract class BaseMultiPolygon {
     feature.set('hidden', false);
 
     let hide = false;
-    if (this.mapBackgroundType === MapBackgroundsEnum.SEMANTIC) {
+    if (this.mapBackgroundType === MapBackgroundsEnum.SEMANTIC && scale < 0.34) {
       const semanticViewData = handleSemanticView(
         this.vectorSource,
         feature,
         resolution,
-        scale,
         this.compartmentId,
         this.complexId,
       );
@@ -286,8 +283,6 @@ export default abstract class BaseMultiPolygon {
     }
 
     let type: string;
-    let fontSize: number;
-    let text: string;
     let coverStyle: Style | undefined;
     let strokeStyle: Stroke | undefined;
 
@@ -295,8 +290,6 @@ export default abstract class BaseMultiPolygon {
       const styleGeometry = style.getGeometry();
       if (styleGeometry instanceof Polygon) {
         type = styleGeometry.get('type');
-        text = styleGeometry.get('text');
-        fontSize = styleGeometry.get('fontSize') || 10;
         coverStyle = styleGeometry.get('coverStyle');
         strokeStyle = styleGeometry.get('strokeStyle');
       }
@@ -317,17 +310,13 @@ export default abstract class BaseMultiPolygon {
         return;
       }
 
-      if (
-        [MAP_ELEMENT_TYPES.MODIFICATION, MAP_ELEMENT_TYPES.TEXT].includes(type) &&
-        scale * fontSize <= 4
-      ) {
+      if ([MAP_ELEMENT_TYPES.MODIFICATION, MAP_ELEMENT_TYPES.TEXT].includes(type) && scale < 0.34) {
         return;
       }
 
       const textStyle = style.getText();
       if (type === 'text' && textStyle) {
         textStyle.setScale(scale);
-        textStyle.setText(text);
       }
       if (strokeStyle) {
         const lineWidth = strokeStyle.getWidth() || 1;
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts
index 77ab7ebc..15a15c3e 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts
@@ -221,7 +221,6 @@ export default class MapElement extends BaseMultiPolygon {
         mirror: modification.direction && modification.direction === 'RIGHT',
       });
       modificationPolygon.set('type', MAP_ELEMENT_TYPES.MODIFICATION);
-      modificationPolygon.set('fontSize', modification.fontSize);
       const modificationStrokeStyle = getStroke({ color: rgbToHex(modification.borderColor) });
       const modificationStyle = new Style({
         geometry: modificationPolygon,
@@ -252,8 +251,6 @@ export default class MapElement extends BaseMultiPolygon {
         [modificationTextCoords, modificationTextCoords],
       ]);
       modificationTextPolygon.set('type', MAP_ELEMENT_TYPES.TEXT);
-      modificationTextPolygon.set('text', modificationText);
-      modificationTextPolygon.set('fontSize', modification.fontSize);
       const modificationTextStyle = getTextStyle({
         text: modificationText,
         fontSize: modification.fontSize,
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.test.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.test.ts
index 0b7e01e1..3c4ae01b 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.test.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.test.ts
@@ -50,7 +50,7 @@ describe('handleSemanticView', () => {
     (getDividedExtents as jest.Mock).mockReturnValue([[0, 0, 10, 5]]);
     (findLargestExtent as jest.Mock).mockReturnValue([0, 0, 10, 5]);
 
-    const result = handleSemanticView(vectorSource, feature, 1, 0.5, null);
+    const result = handleSemanticView(vectorSource, feature, 1, null);
 
     expect(result).toEqual({
       cover: true,
@@ -69,12 +69,12 @@ describe('handleSemanticView', () => {
       .spyOn(vectorSource, 'getFeatureById')
       .mockImplementation(id => (id === 1 ? complexFeature : null));
 
-    const result = handleSemanticView(vectorSource, feature, 1, 1, null, 1);
+    const result = handleSemanticView(vectorSource, feature, 1, null, 1);
 
     expect(result).toEqual({
-      cover: false,
+      cover: true,
       hide: true,
-      largestExtent: null,
+      largestExtent: [0, 0, 10, 5],
     });
 
     expect(feature.get('hidden')).toBe(true);
@@ -86,27 +86,14 @@ describe('handleSemanticView', () => {
       .spyOn(vectorSource, 'getFeatureById')
       .mockImplementation(id => (id === 2 ? compartmentFeature : null));
 
-    const result = handleSemanticView(vectorSource, feature, 1, 1, 2);
+    const result = handleSemanticView(vectorSource, feature, 1, 2);
 
     expect(result).toEqual({
-      cover: false,
+      cover: true,
       hide: true,
-      largestExtent: null,
+      largestExtent: [0, 0, 10, 5],
     });
 
     expect(feature.get('hidden')).toBe(true);
   });
-
-  it('should return cover = false and hide = false when feature does not meet any conditions', () => {
-    const result = handleSemanticView(vectorSource, feature, 1, 1, null);
-
-    expect(result).toEqual({
-      cover: false,
-      hide: false,
-      largestExtent: null,
-    });
-
-    expect(feature.get('filled')).toBe(false);
-    expect(feature.get('hidden')).toBe(false);
-  });
 });
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts
index 83269b75..19619484 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts
@@ -9,7 +9,6 @@ export default function handleSemanticView(
   vectorSource: VectorSource,
   feature: Feature,
   resolution: number,
-  scale: number,
   compartmentId: number | null,
   complexId?: number | null,
 ): { cover: boolean; hide: boolean; largestExtent: Extent | null } {
@@ -28,7 +27,7 @@ export default function handleSemanticView(
         Math.abs(featureExtent[2] - featureExtent[0]) *
         Math.abs(featureExtent[3] - featureExtent[1]);
       coverRatio = compartmentArea / mapArea;
-      if (coverRatio < 0.05 && scale < 1) {
+      if (coverRatio < 0.05) {
         cover = true;
         let remainingExtents = [featureExtent];
         vectorSource.forEachFeatureIntersectingExtent(featureExtent, intersectingFeature => {
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 afeeeeab..0a611adc 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts
@@ -364,10 +364,9 @@ export default class Reaction {
     const styles: Array<Style> = [];
     const scale = this.minResolution / resolution;
     const type = feature.get('elementType');
-    const fontSize = feature.get('fontSize');
     let strokeStyle: Stroke | undefined;
 
-    if (type === REACTION_ELEMENT_TYPES.OPERATOR && fontSize * scale <= 4) {
+    if (type === REACTION_ELEMENT_TYPES.OPERATOR && scale < 0.34) {
       return [];
     }
     if (type === REACTION_ELEMENT_TYPES.ARROW && scale <= 0.125) {
diff --git a/src/redux/map/map.constants.ts b/src/redux/map/map.constants.ts
index 90648de6..55b67d50 100644
--- a/src/redux/map/map.constants.ts
+++ b/src/redux/map/map.constants.ts
@@ -73,7 +73,7 @@ export const MAP_INITIAL_STATE: MapState = {
   loading: 'idle',
   error: { name: '', message: '' },
   openedMaps: OPENED_MAPS_INITIAL_STATE,
-  backgroundType: MapBackgroundsEnum.NETWORK,
+  backgroundType: MapBackgroundsEnum.SEMANTIC,
 };
 
 export const INIT_MAP_SIZE_MODEL_ID_ERROR_PREFIX = 'Failed to initialize map size and model ID';
-- 
GitLab


From 8de23a71194a99132129f125025e9c8f9a06c26b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mi=C5=82osz=20Grocholewski?= <m.grocholewski@atcomp.pl>
Date: Fri, 13 Dec 2024 11:08:40 +0100
Subject: [PATCH 4/4] fix(vector-map): use constants istead of hardcoded values

---
 .../MapViewerVector.constants.ts              | 35 +++++++++++--------
 .../utils/shapes/elements/BaseMultiPolygon.ts | 20 ++++++++---
 .../utils/shapes/elements/Compartment.ts      |  2 +-
 .../shapes/elements/CompartmentPathway.ts     |  2 +-
 .../shapes/elements/handleSemanticView.ts     |  5 +--
 .../utils/shapes/layer/Layer.ts               |  3 +-
 .../utils/shapes/reaction/Reaction.ts         |  9 +++--
 .../MapViewerVector/utils/shapes/text/Text.ts | 12 +++----
 8 files changed, 50 insertions(+), 38 deletions(-)

diff --git a/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts b/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts
index 5bc52a7f..614d3dcf 100644
--- a/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts
@@ -4,6 +4,11 @@ export const VECTOR_MAP_LAYER_TYPE = 'vectorMapLayer';
 
 export const COMPLEX_SBO_TERMS = ['SBO:0000253', 'SBO:0000297', 'SBO:0000289'];
 
+export const TEXT_CUTOFF_SCALE = 0.34;
+export const OUTLINE_CUTOFF_SCALE = 0.18;
+export const COMPLEX_CONTENTS_CUTOFF_SCALE = 0.215;
+export const REACTION_ELEMENT_CUTOFF_SCALE = 0.125;
+
 export const WHITE_COLOR: Color = {
   alpha: 255,
   rgb: 16777215,
@@ -20,27 +25,27 @@ export const TRANSPARENT_COLOR: Color = {
 };
 
 export const REACTION_ELEMENT_TYPES = {
-  OPERATOR: 'operator',
-  SQUARE: 'square',
-  LINE: 'line',
-  ARROW: 'arrow',
+  OPERATOR: 'OPERATOR',
+  SQUARE: 'SQUARE',
+  LINE: 'LINE',
+  ARROW: 'ARROW',
 };
 
 export const MAP_ELEMENT_TYPES = {
-  TEXT: 'text',
-  MODIFICATION: 'modification',
-  ACTIVITY_BORDER: 'activityBorder',
-  ENTITY: 'entity',
-  OVERLAY: 'overlay',
-  COMPARTMENT: 'compartment',
+  TEXT: 'TEXT',
+  MODIFICATION: 'MODIFICATION',
+  ACTIVITY_BORDER: 'ACTIVITY_BORDER',
+  ENTITY: 'ENTITY',
+  OVERLAY: 'OVERLAY',
+  COMPARTMENT: 'COMPARTMENT',
 };
 
 export const LAYER_ELEMENT_TYPES = {
-  TEXT: 'text',
-  OVAL: 'oval',
-  RECT: 'rect',
-  LINE: 'line',
-  ARROW: 'arrow',
+  TEXT: 'TEXT',
+  OVAL: 'OVAL',
+  RECT: 'RECT',
+  LINE: 'LINE',
+  ARROW: 'ARROW',
 };
 
 export const COMPARTMENT_SQUARE_POINTS: Array<ShapeRelAbs | ShapeRelAbsBezierPoint> = [
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 fd2f74fd..ed6fe198 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/BaseMultiPolygon.ts
@@ -14,8 +14,11 @@ import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shape
 import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords';
 import { Color } from '@/types/models';
 import {
+  COMPLEX_CONTENTS_CUTOFF_SCALE,
   COMPLEX_SBO_TERMS,
   MAP_ELEMENT_TYPES,
+  OUTLINE_CUTOFF_SCALE,
+  TEXT_CUTOFF_SCALE,
 } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
 import VectorSource from 'ol/source/Vector';
 import MapBackgroundsEnum from '@/redux/map/map.enums';
@@ -258,14 +261,18 @@ export default abstract class BaseMultiPolygon {
     let cover = false;
     let largestExtent: Extent | null;
 
-    if (this.complexId && !COMPLEX_SBO_TERMS.includes(this.sboTerm) && scale < 0.215) {
+    if (
+      this.complexId &&
+      !COMPLEX_SBO_TERMS.includes(this.sboTerm) &&
+      scale < COMPLEX_CONTENTS_CUTOFF_SCALE
+    ) {
       feature.set('hidden', true);
       return [];
     }
     feature.set('hidden', false);
 
     let hide = false;
-    if (this.mapBackgroundType === MapBackgroundsEnum.SEMANTIC && scale < 0.34) {
+    if (this.mapBackgroundType === MapBackgroundsEnum.SEMANTIC && scale < TEXT_CUTOFF_SCALE) {
       const semanticViewData = handleSemanticView(
         this.vectorSource,
         feature,
@@ -310,19 +317,22 @@ export default abstract class BaseMultiPolygon {
         return;
       }
 
-      if ([MAP_ELEMENT_TYPES.MODIFICATION, MAP_ELEMENT_TYPES.TEXT].includes(type) && scale < 0.34) {
+      if (
+        [MAP_ELEMENT_TYPES.MODIFICATION, MAP_ELEMENT_TYPES.TEXT].includes(type) &&
+        scale < TEXT_CUTOFF_SCALE
+      ) {
         return;
       }
 
       const textStyle = style.getText();
-      if (type === 'text' && textStyle) {
+      if (type === MAP_ELEMENT_TYPES.TEXT && textStyle) {
         textStyle.setScale(scale);
       }
       if (strokeStyle) {
         const lineWidth = strokeStyle.getWidth() || 1;
         if (
           !this.overlaysVisible &&
-          scale < 0.18 &&
+          scale < OUTLINE_CUTOFF_SCALE &&
           !COMPLEX_SBO_TERMS.includes(this.sboTerm) &&
           this.type !== MAP_ELEMENT_TYPES.COMPARTMENT
         ) {
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment.ts
index 8906e75d..987fd2ce 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment.ts
@@ -97,7 +97,7 @@ export default abstract class Compartment extends BaseMultiPolygon {
     mapSize,
   }: CompartmentProps) {
     super({
-      type: 'COMPARTMENT',
+      type: MAP_ELEMENT_TYPES.COMPARTMENT,
       id,
       complexId,
       compartmentId,
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.ts
index e758a681..2850176f 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/CompartmentPathway.ts
@@ -87,7 +87,7 @@ export default class CompartmentPathway extends BaseMultiPolygon {
     mapSize,
   }: CompartmentPathwayProps) {
     super({
-      type: 'COMPARTMENT',
+      type: MAP_ELEMENT_TYPES.COMPARTMENT,
       id,
       complexId,
       compartmentId,
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts
index 19619484..b329d609 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts
@@ -4,6 +4,7 @@ import findLargestExtent from '@/components/Map/MapViewer/MapViewerVector/utils/
 import Feature from 'ol/Feature';
 import VectorSource from 'ol/source/Vector';
 import { Extent } from 'ol/extent';
+import { MAP_ELEMENT_TYPES } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
 
 export default function handleSemanticView(
   vectorSource: VectorSource,
@@ -18,7 +19,7 @@ export default function handleSemanticView(
   let cover = false;
   let hide = false;
   let largestExtent: Extent | null = null;
-  if (getMapExtent instanceof Function && type === 'COMPARTMENT') {
+  if (getMapExtent instanceof Function && type === MAP_ELEMENT_TYPES.COMPARTMENT) {
     const mapExtent = getMapExtent(resolution);
     const featureExtent = feature.getGeometry()?.getExtent();
     if (featureExtent && mapExtent) {
@@ -33,7 +34,7 @@ export default function handleSemanticView(
         vectorSource.forEachFeatureIntersectingExtent(featureExtent, intersectingFeature => {
           if (
             !intersectingFeature.get('hidden') &&
-            intersectingFeature.get('type') === 'COMPARTMENT' &&
+            intersectingFeature.get('type') === MAP_ELEMENT_TYPES.COMPARTMENT &&
             intersectingFeature.get('zIndex') > feature.get('zIndex') &&
             intersectingFeature.get('filled')
           ) {
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 29f17e00..0b8d6403 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/layer/Layer.ts
@@ -21,6 +21,7 @@ import Style from 'ol/style/Style';
 import { ArrowTypeDict, LineTypeDict } from '@/redux/shapes/shapes.types';
 import {
   LAYER_ELEMENT_TYPES,
+  REACTION_ELEMENT_CUTOFF_SCALE,
   TRANSPARENT_COLOR,
 } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
 import getScaledElementStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getScaledElementStyle';
@@ -305,7 +306,7 @@ export default class Layer {
     let strokeStyle: Stroke | undefined;
     const type = feature.get('elementType');
 
-    if (type === LAYER_ELEMENT_TYPES.ARROW && scale <= 0.08) {
+    if (type === LAYER_ELEMENT_TYPES.ARROW && scale <= REACTION_ELEMENT_CUTOFF_SCALE) {
       return [];
     }
 
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 0a611adc..a2a4a38a 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/reaction/Reaction.ts
@@ -7,7 +7,9 @@ import getStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/st
 import Polygon from 'ol/geom/Polygon';
 import Style from 'ol/style/Style';
 import {
+  REACTION_ELEMENT_CUTOFF_SCALE,
   REACTION_ELEMENT_TYPES,
+  TEXT_CUTOFF_SCALE,
   WHITE_COLOR,
 } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
 import { FeatureLike } from 'ol/Feature';
@@ -366,10 +368,7 @@ export default class Reaction {
     const type = feature.get('elementType');
     let strokeStyle: Stroke | undefined;
 
-    if (type === REACTION_ELEMENT_TYPES.OPERATOR && scale < 0.34) {
-      return [];
-    }
-    if (type === REACTION_ELEMENT_TYPES.ARROW && scale <= 0.125) {
+    if (type === REACTION_ELEMENT_TYPES.OPERATOR && scale < TEXT_CUTOFF_SCALE) {
       return [];
     }
 
@@ -402,7 +401,7 @@ export default class Reaction {
     const scale = this.minResolution / resolution;
     let strokeStyle: Stroke | undefined;
 
-    if (scale <= 0.125) {
+    if (scale <= REACTION_ELEMENT_CUTOFF_SCALE) {
       return [];
     }
 
diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.ts
index 6d84b083..27b8ec6f 100644
--- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.ts
+++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/text/Text.ts
@@ -13,6 +13,7 @@ import { MapInstance } from '@/types/map';
 import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords';
 import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle';
 import { Color } from '@/types/models';
+import { TEXT_CUTOFF_SCALE } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
 
 export interface TextProps {
   x: number;
@@ -101,15 +102,10 @@ export default class Text {
     if (getTextScale instanceof Function) {
       textScale = getTextScale(resolution);
     }
-
-    if (this.style.getText()) {
-      if (this.fontSize * textScale > 4) {
-        this.style.getText()?.setScale(textScale);
-        this.style.getText()?.setText(this.text);
-      } else {
-        this.style.getText()?.setText(undefined);
-      }
+    if (textScale < TEXT_CUTOFF_SCALE) {
+      return undefined;
     }
+    this.style.getText()?.setScale(textScale);
     return this.style;
   }
 }
-- 
GitLab