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 6e52b495d0a18d95ad94e2cbe5a104b3e7d48178..d61918dc32b529f6a7330f93fe21b64573bef0c4 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/config/reactionsLayer/useOlMapReactionsLayer.ts @@ -61,6 +61,8 @@ export const useOlMapReactionsLayer = ({ borderColor: element.borderColor, nameVerticalAlign: element.nameVerticalAlign as VerticalAlign, nameHorizontalAlign: element.nameHorizontalAlign as HorizontalAlign, + homodimer: element.homodimer, + activity: element.activity, text: element.name, fontSize: element.fontSize, pointToProjection, diff --git a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/MapElement.ts b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/MapElement.ts index f1ba348fd4ef6b2602eb4a26fbe13e16f52bba41..2e72e1a78043289e166717137f97e72a448cdcd9 100644 --- a/src/components/Map/MapViewer/MapViewerVector/utils/shapes/MapElement.ts +++ b/src/components/Map/MapViewer/MapViewerVector/utils/shapes/MapElement.ts @@ -39,6 +39,8 @@ export type MapElementProps = { nameWidth: number; nameVerticalAlign?: VerticalAlign; nameHorizontalAlign?: HorizontalAlign; + homodimer?: number; + activity?: boolean; pointToProjection: UsePointToProjectionResult; mapInstance: MapInstance; bioShapes?: Array<BioShape>; @@ -57,8 +59,14 @@ export default class MapElement extends BaseMultiPolygon { lineTypes: Array<LineType>; + homodimer: number; + + activity: boolean | undefined; + modifications: Array<Modification>; + lineDash: Array<number> = []; + constructor({ shapes, x, @@ -79,6 +87,8 @@ export default class MapElement extends BaseMultiPolygon { nameWidth, nameVerticalAlign = 'MIDDLE', nameHorizontalAlign = 'CENTER', + homodimer = 1, + activity, pointToProjection, mapInstance, bioShapes = [], @@ -107,6 +117,8 @@ export default class MapElement extends BaseMultiPolygon { this.shapes = shapes; this.lineWidth = lineWidth; this.lineType = lineType; + this.homodimer = homodimer; + this.activity = activity; this.bioShapes = bioShapes; this.lineTypes = lineTypes; this.modifications = modifications; @@ -116,7 +128,7 @@ export default class MapElement extends BaseMultiPolygon { } protected createPolygons(): void { - const multiPolygon: Array<Polygon> = []; + let multiPolygonModifications: Array<Polygon> = []; this.modifications.forEach(modification => { if (modification.state === null) { return; @@ -126,7 +138,7 @@ export default class MapElement extends BaseMultiPolygon { if (!shape) { return; } - const multiPolygonModification = getMultiPolygon({ + multiPolygonModifications = getMultiPolygon({ x: modification.x, y: modification.y, width: modification.width, @@ -135,8 +147,8 @@ export default class MapElement extends BaseMultiPolygon { pointToProjection: this.pointToProjection, mirror: modification.direction && modification.direction === 'RIGHT', }); - multiPolygon.push(...multiPolygonModification.flat()); - multiPolygonModification.forEach(polygon => { + this.polygons.push(...multiPolygonModifications); + multiPolygonModifications.forEach(polygon => { const modificationStyle = new Style({ geometry: polygon, stroke: getStroke({ color: rgbToHex(modification.borderColor) }), @@ -163,32 +175,70 @@ export default class MapElement extends BaseMultiPolygon { }); }); - const elementMultiPolygon = getMultiPolygon({ - x: this.x, - y: this.y, - width: this.width, - height: this.height, - shapes: this.shapes, - pointToProjection: this.pointToProjection, - }); - this.polygons = [...this.polygons, ...multiPolygon, ...elementMultiPolygon.flat()]; - - let lineDash: Array<number> = []; if (this.lineType) { const lineTypeFound = this.lineTypes.find(type => type.name === this.lineType); if (lineTypeFound) { - lineDash = lineTypeFound.pattern; + this.lineDash = lineTypeFound.pattern; } } - elementMultiPolygon.forEach(polygon => { + + const homodimerOffset = (this.homodimer - 1) * 6; + for (let i = 0; i < this.homodimer; i += 1) { + const homodimerShift = (this.homodimer - i - 1) * 6; + if (this.activity) { + this.drawActiveBorder(homodimerShift, homodimerOffset); + } + this.drawElementPolygon(homodimerShift, homodimerOffset); + } + } + + drawActiveBorder(homodimerShift: number, homodimerOffset: number): void { + const activityBorderElement = getMultiPolygon({ + x: this.x + homodimerShift - 5, + y: this.y + homodimerShift - 5, + width: this.width - homodimerOffset + 10, + height: this.height - homodimerOffset + 10, + shapes: this.shapes, + pointToProjection: this.pointToProjection, + }); + activityBorderElement.forEach(polygon => { + this.styles.push( + new Style({ + geometry: polygon, + fill: getFill({ color: 'rgba(0, 0, 0, 0)' }), + stroke: getStroke({ + lineDash: [3, 5], + }), + zIndex: this.zIndex, + }), + ); + }); + this.polygons.push(...activityBorderElement); + } + + drawElementPolygon(homodimerShift: number, homodimerOffset: number): void { + const elementPolygon = getMultiPolygon({ + x: this.x + homodimerShift, + y: this.y + homodimerShift, + width: this.width - homodimerOffset, + height: this.height - homodimerOffset, + shapes: this.shapes, + pointToProjection: this.pointToProjection, + }); + elementPolygon.forEach(polygon => { this.styles.push( new Style({ geometry: polygon, - stroke: getStroke({ color: rgbToHex(this.borderColor), width: this.lineWidth, lineDash }), + stroke: getStroke({ + color: rgbToHex(this.borderColor), + width: this.lineWidth, + lineDash: this.lineDash, + }), fill: getFill({ color: rgbToHex(this.fillColor) }), zIndex: this.zIndex, }), ); }); + this.polygons.push(...elementPolygon); } } diff --git a/src/models/modelElementSchema.ts b/src/models/modelElementSchema.ts index 3f650899441c4ef31cbba8dba6f640eedc51a5b7..98f2882560db3d36ae8b4a7e415b506e2e3e083f 100644 --- a/src/models/modelElementSchema.ts +++ b/src/models/modelElementSchema.ts @@ -46,7 +46,7 @@ export const modelElementSchema = z.object({ charge: z.number().nullable().optional(), initialConcentration: z.number().nullable().optional(), onlySubstanceUnits: z.boolean().nullable().optional(), - homodimer: z.number().nullable().optional(), + homodimer: z.number().optional(), hypothetical: z.boolean().nullable().optional(), boundaryCondition: z.boolean().nullable().optional(), constant: z.boolean().nullable().optional(),