diff --git a/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts b/src/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants.ts index 5bc52a7fd486077744fe048effab865d59c6639e..614d3dcf06a521ffb3fe170362e760b59905086b 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 30f48a793a787e7719a02a024a5e9e3a5bf301ec..ed6fe198504b2f721fa0c382302c58e46fc35eac 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'; @@ -196,8 +199,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, @@ -260,19 +261,22 @@ 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) { + if (this.mapBackgroundType === MapBackgroundsEnum.SEMANTIC && scale < TEXT_CUTOFF_SCALE) { const semanticViewData = handleSemanticView( this.vectorSource, feature, resolution, - scale, this.compartmentId, this.complexId, ); @@ -286,8 +290,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 +297,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'); } @@ -319,21 +319,20 @@ export default abstract class BaseMultiPolygon { if ( [MAP_ELEMENT_TYPES.MODIFICATION, MAP_ELEMENT_TYPES.TEXT].includes(type) && - scale * fontSize <= 4 + scale < TEXT_CUTOFF_SCALE ) { return; } const textStyle = style.getText(); - if (type === 'text' && textStyle) { + if (type === MAP_ELEMENT_TYPES.TEXT && textStyle) { textStyle.setScale(scale); - textStyle.setText(text); } 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 8906e75dab9219c5aa4b370254c564f5dc3eedc5..987fd2cee18029603d330e2f7512ac7069554ba5 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 e758a681ec3addb34553e58e79ed8085b72aa6e2..2850176f0d50cf9617d7fa0ea50bd33aa6732b57 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/MapElement.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/MapElement.ts index 77ab7ebc56e566cf25e5c2281d60f05d1a2f7d68..15a15c3e1d83125baf7fc92589cf8ad2c76e3d19 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 0b7e01e1131522f36a917e49f25213d7d7aa6189..3c4ae01b5b599c028b8163c4cbcee3129f607bfb 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 83269b75f248c1e41a8b44b8fcb2e7b7160f1448..b329d6095233df50f1621f858dacdec526ea6bdf 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/handleSemanticView.ts @@ -4,12 +4,12 @@ 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, feature: Feature, resolution: number, - scale: number, compartmentId: number | null, complexId?: number | null, ): { cover: boolean; hide: boolean; largestExtent: Extent | null } { @@ -19,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) { @@ -28,13 +28,13 @@ 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 => { 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 29f17e00af39fb20d135bf1784b5abeb03a83737..0b8d6403d8ebc05700fe6e32a8ce71e988000aaf 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 afeeeeab62cb3c6d44a93abdb68239640aca7aec..a2a4a38ab8c1d98abedbf7b4071a1c860204aca1 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'; @@ -364,13 +366,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) { - return []; - } - if (type === REACTION_ELEMENT_TYPES.ARROW && scale <= 0.125) { + if (type === REACTION_ELEMENT_TYPES.OPERATOR && scale < TEXT_CUTOFF_SCALE) { return []; } @@ -403,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 6d84b083bd1cfda2dd3fc15f5ebcdc0a4d417070..27b8ec6f59260848cfeb6581ee1c8e91b99f61d8 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; } } diff --git a/src/redux/map/map.constants.ts b/src/redux/map/map.constants.ts index 90648de6c76b7eab6ed8e70fab2188f9cc15e28f..55b67d50eb035d951828d2d97e23891ebaee4a83 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';