Skip to content
Snippets Groups Projects
Commit 275ee483 authored by Miłosz Grocholewski's avatar Miłosz Grocholewski
Browse files

Merge branch 'feat/MIN-25-modifications' into 'development'

feat(vector-map): add modifications for map elements

Closes MIN-25

See merge request !258
parents ed740e71 eaf60ac5
No related branches found
No related tags found
1 merge request!258feat(vector-map): add modifications for map elements
Pipeline #96665 passed
Showing
with 208 additions and 55 deletions
...@@ -4,7 +4,7 @@ import VectorLayer from 'ol/layer/Vector'; ...@@ -4,7 +4,7 @@ import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector'; import VectorSource from 'ol/source/Vector';
import { useEffect, useMemo } from 'react'; import { useEffect, useMemo } from 'react';
import { usePointToProjection } from '@/utils/map/usePointToProjection'; import { usePointToProjection } from '@/utils/map/usePointToProjection';
import CustomMultiPolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/CustomMultiPolygon'; import MapElement from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/MapElement';
import { useSelector } from 'react-redux'; import { useSelector } from 'react-redux';
import { shapesSelector } from '@/redux/shapes/shapes.selectors'; import { shapesSelector } from '@/redux/shapes/shapes.selectors';
import { MapInstance } from '@/types/map'; import { MapInstance } from '@/types/map';
...@@ -37,7 +37,7 @@ export const useOlMapReactionsLayer = ({ ...@@ -37,7 +37,7 @@ export const useOlMapReactionsLayer = ({
return modelElements.content.map(element => { return modelElements.content.map(element => {
const shape = shapes.data.find(bioShape => bioShape.sboTerm === element.sboTerm); const shape = shapes.data.find(bioShape => bioShape.sboTerm === element.sboTerm);
if (shape) { if (shape) {
return new CustomMultiPolygon({ return new MapElement({
shapes: shape.shapes, shapes: shape.shapes,
x: element.x, x: element.x,
y: element.y, y: element.y,
...@@ -57,6 +57,8 @@ export const useOlMapReactionsLayer = ({ ...@@ -57,6 +57,8 @@ export const useOlMapReactionsLayer = ({
text: element.name, text: element.name,
pointToProjection, pointToProjection,
mapInstance, mapInstance,
modifications: element.modificationResidues,
bioShapes: shapes.data,
}); });
} }
return undefined; return undefined;
...@@ -67,7 +69,7 @@ export const useOlMapReactionsLayer = ({ ...@@ -67,7 +69,7 @@ export const useOlMapReactionsLayer = ({
const features = useMemo(() => { const features = useMemo(() => {
return elements return elements
.filter((element): element is CustomMultiPolygon => element !== undefined) .filter((element): element is MapElement => element !== undefined)
.map(element => element.multiPolygonFeature); .map(element => element.multiPolygonFeature);
}, [elements]); }, [elements]);
......
...@@ -7,9 +7,9 @@ import getMultiPolygon from '@/components/Map/MapViewer/MapViewerVector/utils/sh ...@@ -7,9 +7,9 @@ import getMultiPolygon from '@/components/Map/MapViewer/MapViewerVector/utils/sh
import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getStroke'; import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getStroke';
import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getFill'; import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getFill';
import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/rgbToHex'; import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/rgbToHex';
import CustomMultiPolygon, { import MapElement, {
CustomMultiPolygonProps, MapElementProps,
} from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/CustomMultiPolygon'; } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/MapElement';
import View from 'ol/View'; import View from 'ol/View';
import { import {
WHITE_COLOR, WHITE_COLOR,
...@@ -22,8 +22,8 @@ jest.mock('./getStroke'); ...@@ -22,8 +22,8 @@ jest.mock('./getStroke');
jest.mock('./getFill'); jest.mock('./getFill');
jest.mock('./rgbToHex'); jest.mock('./rgbToHex');
describe('CustomMultiPolygon', () => { describe('MapElement', () => {
let props: CustomMultiPolygonProps; let props: MapElementProps;
beforeEach(() => { beforeEach(() => {
const dummyElement = document.createElement('div'); const dummyElement = document.createElement('div');
...@@ -88,7 +88,7 @@ describe('CustomMultiPolygon', () => { ...@@ -88,7 +88,7 @@ describe('CustomMultiPolygon', () => {
}); });
it('should initialize with correct default properties', () => { it('should initialize with correct default properties', () => {
const multiPolygon = new CustomMultiPolygon(props); const multiPolygon = new MapElement(props);
expect(multiPolygon.polygons.length).toBe(2); expect(multiPolygon.polygons.length).toBe(2);
expect(multiPolygon.multiPolygonFeature).toBeInstanceOf(Feature); expect(multiPolygon.multiPolygonFeature).toBeInstanceOf(Feature);
...@@ -96,7 +96,7 @@ describe('CustomMultiPolygon', () => { ...@@ -96,7 +96,7 @@ describe('CustomMultiPolygon', () => {
}); });
it('should apply correct styles to the feature', () => { it('should apply correct styles to the feature', () => {
const multiPolygon = new CustomMultiPolygon(props); const multiPolygon = new MapElement(props);
const feature = multiPolygon.multiPolygonFeature; const feature = multiPolygon.multiPolygonFeature;
const style = feature.getStyleFunction()?.call(multiPolygon, feature, 1); const style = feature.getStyleFunction()?.call(multiPolygon, feature, 1);
...@@ -109,7 +109,7 @@ describe('CustomMultiPolygon', () => { ...@@ -109,7 +109,7 @@ describe('CustomMultiPolygon', () => {
}); });
it('should update text style based on resolution', () => { it('should update text style based on resolution', () => {
const multiPolygon = new CustomMultiPolygon(props); const multiPolygon = new MapElement(props);
const feature = multiPolygon.multiPolygonFeature; const feature = multiPolygon.multiPolygonFeature;
multiPolygon.styleFunction(feature, 1000); multiPolygon.styleFunction(feature, 1000);
......
/* eslint-disable no-magic-numbers */ /* eslint-disable no-magic-numbers */
import { Style } from 'ol/style'; import { Style, Text } from 'ol/style';
import Feature, { FeatureLike } from 'ol/Feature'; import Feature, { FeatureLike } from 'ol/Feature';
import { Geometry, MultiPolygon } from 'ol/geom'; import { MultiPolygon } from 'ol/geom';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getStroke'; import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getStroke';
import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getFill'; import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getFill';
import RenderFeature from 'ol/render/Feature';
import Polygon from 'ol/geom/Polygon'; import Polygon from 'ol/geom/Polygon';
import getMultiPolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getMultiPolygon'; import getMultiPolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getMultiPolygon';
import getText from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getText'; import getText from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getText';
import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/rgbToHex'; import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/rgbToHex';
import { Shape } from '@/types/models'; import { BioShape, Modification, Shape } from '@/types/models';
import { MapInstance } from '@/types/map'; import { MapInstance } from '@/types/map';
import { import {
ColorObject, ColorObject,
...@@ -22,7 +21,7 @@ import { ...@@ -22,7 +21,7 @@ import {
WHITE_COLOR, WHITE_COLOR,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants'; } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
export type CustomMultiPolygonProps = { export type MapElementProps = {
shapes: Array<Shape>; shapes: Array<Shape>;
x: number; x: number;
y: number; y: number;
...@@ -43,15 +42,19 @@ export type CustomMultiPolygonProps = { ...@@ -43,15 +42,19 @@ export type CustomMultiPolygonProps = {
nameHorizontalAlign?: HorizontalAlign; nameHorizontalAlign?: HorizontalAlign;
pointToProjection: UsePointToProjectionResult; pointToProjection: UsePointToProjectionResult;
mapInstance: MapInstance; mapInstance: MapInstance;
bioShapes?: Array<BioShape>;
modifications?: Array<Modification>;
}; };
export default class CustomMultiPolygon { export default class MapElement {
multiPolygonStyle: Style;
textStyle: Style | undefined; textStyle: Style | undefined;
polygons: Array<Polygon> = []; polygons: Array<Polygon> = [];
styles: Array<Style> = [];
polygonsTexts: Array<string> = [];
multiPolygonFeature: Feature; multiPolygonFeature: Feature;
constructor({ constructor({
...@@ -75,7 +78,9 @@ export default class CustomMultiPolygon { ...@@ -75,7 +78,9 @@ export default class CustomMultiPolygon {
nameHorizontalAlign = 'CENTER', nameHorizontalAlign = 'CENTER',
pointToProjection, pointToProjection,
mapInstance, mapInstance,
}: CustomMultiPolygonProps) { bioShapes = [],
modifications = [],
}: MapElementProps) {
if (text) { if (text) {
const { textCoords, textStyle } = getText({ const { textCoords, textStyle } = getText({
text, text,
...@@ -85,28 +90,76 @@ export default class CustomMultiPolygon { ...@@ -85,28 +90,76 @@ export default class CustomMultiPolygon {
width: nameWidth, width: nameWidth,
height: nameHeight, height: nameHeight,
color: rgbToHex(fontColor), color: rgbToHex(fontColor),
zIndex,
verticalAlign: nameVerticalAlign, verticalAlign: nameVerticalAlign,
horizontalAlign: nameHorizontalAlign, horizontalAlign: nameHorizontalAlign,
pointToProjection, pointToProjection,
}); });
this.textStyle = new Style({ this.styles.push(textStyle);
geometry: (feature: FeatureLike): Geometry | RenderFeature | undefined => { this.polygonsTexts.push(text);
const geometry = feature.getGeometry();
if (geometry && geometry.getType() === 'MultiPolygon') {
return (geometry as MultiPolygon).getPolygon(0).getInteriorPoint();
}
return undefined;
},
text: textStyle.getText() || undefined,
zIndex,
});
this.polygons.push(new Polygon([[textCoords, textCoords]])); this.polygons.push(new Polygon([[textCoords, textCoords]]));
} }
this.polygons = [ const multiPolygon: Array<Polygon> = [];
...this.polygons, modifications.forEach(modification => {
...getMultiPolygon({ x, y, width, height, shapes, pointToProjection }), if (modification.state === null) {
]; return;
}
const shape = bioShapes.find(bioShape => bioShape.sboTerm === modification.sboTerm);
if (!shape) {
return;
}
const multiPolygonModification = getMultiPolygon({
x: modification.x,
y: modification.y,
width: modification.width,
height: modification.height,
shapes: shape.shapes,
pointToProjection,
mirror: modification.direction && modification.direction === 'RIGHT',
});
multiPolygon.push(...multiPolygonModification.flat());
multiPolygonModification.forEach(polygon => {
const modificationStyle = new Style({
geometry: polygon,
stroke: getStroke({ color: rgbToHex(modification.borderColor) }),
fill: getFill({ color: rgbToHex(modification.fillColor) }),
zIndex: modification.z,
});
const modificationText = modification.stateAbbreviation
? modification.stateAbbreviation
: modification.name;
if (modificationText) {
modificationStyle.setText(
new Text({
text: modificationText,
font: `${modification.fontSize}px Arial`,
textAlign: 'center',
textBaseline: 'middle',
fill: getFill({ color: '#000' }),
overflow: true,
}),
);
this.polygonsTexts.push(modification.name);
}
this.styles.push(modificationStyle);
});
});
const elementMultiPolygon = getMultiPolygon({ x, y, width, height, shapes, pointToProjection });
this.polygons = [...this.polygons, ...multiPolygon, ...elementMultiPolygon.flat()];
elementMultiPolygon.forEach(polygon => {
this.styles.push(
new Style({
geometry: polygon,
stroke: getStroke({ color: rgbToHex(borderColor), width: lineWidth }),
fill: getFill({ color: rgbToHex(fillColor) }),
zIndex,
}),
);
});
this.multiPolygonFeature = new Feature({ this.multiPolygonFeature = new Feature({
geometry: new MultiPolygon([...this.polygons]), geometry: new MultiPolygon([...this.polygons]),
...@@ -122,12 +175,6 @@ export default class CustomMultiPolygon { ...@@ -122,12 +175,6 @@ export default class CustomMultiPolygon {
}, },
}); });
this.multiPolygonStyle = new Style({
stroke: getStroke({ color: rgbToHex(borderColor), width: lineWidth }),
fill: getFill({ color: rgbToHex(fillColor) }),
zIndex,
});
this.multiPolygonFeature.setStyle(this.styleFunction.bind(this)); this.multiPolygonFeature.setStyle(this.styleFunction.bind(this));
} }
...@@ -137,14 +184,18 @@ export default class CustomMultiPolygon { ...@@ -137,14 +184,18 @@ export default class CustomMultiPolygon {
if (getTextScale instanceof Function) { if (getTextScale instanceof Function) {
textScale = getTextScale(resolution); textScale = getTextScale(resolution);
} }
const styles = []; let index = 0;
if (this.textStyle) { this.styles.forEach(style => {
const text = this.textStyle.getText(); if (style.getText()) {
if (text) { if (textScale > 0.3) {
this.textStyle.getText()?.setScale(textScale); style.getText()?.setScale(textScale);
styles.push(this.textStyle); style.getText()?.setText(this.polygonsTexts[index]);
index += 1;
} else {
style.getText()?.setText(undefined);
}
} }
} });
return [...styles, this.multiPolygonStyle]; return this.styles;
} }
} }
/* eslint-disable no-magic-numbers */
import { Coordinate } from 'ol/coordinate';
import getCentroid from './getCentroid';
describe('getCentroid', () => {
it('should return a centroid for coordinates', () => {
const coords: Array<Coordinate> = [
[0, 0],
[20, 0],
[35, 10],
[20, 20],
[10, 30],
[0, 20],
];
const result = getCentroid(coords);
expect(result[0]).toBeCloseTo(13.46);
expect(result[1]).toBeCloseTo(12.05);
});
});
/* eslint-disable no-magic-numbers */
import { Coordinate } from 'ol/coordinate';
export default function getCentroid(coords: Array<Coordinate>): Coordinate {
let area = 0;
let centroidX = 0;
let centroidY = 0;
const numPoints = coords.length;
for (let i = 0; i < numPoints; i += 1) {
const x1 = coords[i][0];
const y1 = coords[i][1];
const x2 = coords[(i + 1) % numPoints][0];
const y2 = coords[(i + 1) % numPoints][1];
const crossProduct = x1 * y2 - x2 * y1;
area += crossProduct;
centroidX += (x1 + x2) * crossProduct;
centroidY += (y1 + y2) * crossProduct;
}
area /= 2;
centroidX /= 6 * area;
centroidY /= 6 * area;
return [centroidX, centroidY];
}
...@@ -30,7 +30,7 @@ export default function getEllipseCoords({ ...@@ -30,7 +30,7 @@ export default function getEllipseCoords({
height, height,
width, width,
pointToProjection, pointToProjection,
points = 64, points = 20,
}: { }: {
x: number; x: number;
y: number; y: number;
......
/* eslint-disable no-magic-numbers */
import getPolygonCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getPolygonCoords'; import getPolygonCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getPolygonCoords';
import getEllipseCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getEllipseCoords'; import getEllipseCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getEllipseCoords';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import Polygon from 'ol/geom/Polygon'; import Polygon from 'ol/geom/Polygon';
import { Coordinate } from 'ol/coordinate'; import { Coordinate } from 'ol/coordinate';
import { Shape } from '@/types/models'; import { Shape } from '@/types/models';
import getCentroid from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/getCentroid';
export default function getMultiPolygon({ export default function getMultiPolygon({
x, x,
...@@ -12,6 +14,7 @@ export default function getMultiPolygon({ ...@@ -12,6 +14,7 @@ export default function getMultiPolygon({
height, height,
shapes, shapes,
pointToProjection, pointToProjection,
mirror,
}: { }: {
x: number; x: number;
y: number; y: number;
...@@ -19,6 +22,7 @@ export default function getMultiPolygon({ ...@@ -19,6 +22,7 @@ export default function getMultiPolygon({
height: number; height: number;
shapes: Array<Shape>; shapes: Array<Shape>;
pointToProjection: UsePointToProjectionResult; pointToProjection: UsePointToProjectionResult;
mirror?: boolean;
}): Array<Polygon> { }): Array<Polygon> {
return shapes.map(shape => { return shapes.map(shape => {
let coords: Array<Coordinate> = []; let coords: Array<Coordinate> = [];
...@@ -35,6 +39,17 @@ export default function getMultiPolygon({ ...@@ -35,6 +39,17 @@ export default function getMultiPolygon({
pointToProjection, pointToProjection,
}); });
} }
if (mirror) {
const centroid = getCentroid(coords);
coords = coords.map(coord => {
const mirroredX = 2 * centroid[0] - coord[0];
return [mirroredX, coord[1]];
});
}
return new Polygon([coords]); return new Polygon([coords]);
}); });
} }
...@@ -48,6 +48,6 @@ export default function getPolygonCoords({ ...@@ -48,6 +48,6 @@ export default function getPolygonCoords({
return [[...lastPoint]]; return [[...lastPoint]];
} }
const { p1, p2, p3 } = getCurveCoords({ x, y, point, height, width, pointToProjection }); const { p1, p2, p3 } = getCurveCoords({ x, y, point, height, width, pointToProjection });
return getBezierCurve({ p0: lastPoint, p1, p2, p3, numPoints: 50 }); return getBezierCurve({ p0: lastPoint, p1, p2, p3, numPoints: 20 });
}); });
} }
...@@ -2,13 +2,14 @@ ...@@ -2,13 +2,14 @@
import { Fill, Text } from 'ol/style'; import { Fill, Text } from 'ol/style';
import Style from 'ol/style/Style'; import Style from 'ol/style/Style';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection'; import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { Feature } from 'ol';
import { Point } from 'ol/geom';
import { Coordinate } from 'ol/coordinate'; import { Coordinate } from 'ol/coordinate';
import { import {
HorizontalAlign, HorizontalAlign,
VerticalAlign, VerticalAlign,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types'; } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
import { FeatureLike } from 'ol/Feature';
import { Geometry, MultiPolygon } from 'ol/geom';
import RenderFeature from 'ol/render/Feature';
export default function getText({ export default function getText({
x, x,
...@@ -18,6 +19,7 @@ export default function getText({ ...@@ -18,6 +19,7 @@ export default function getText({
text = '', text = '',
fontSize = 12, fontSize = 12,
color = '#000', color = '#000',
zIndex = 1,
verticalAlign = 'MIDDLE', verticalAlign = 'MIDDLE',
horizontalAlign = 'CENTER', horizontalAlign = 'CENTER',
pointToProjection, pointToProjection,
...@@ -29,6 +31,7 @@ export default function getText({ ...@@ -29,6 +31,7 @@ export default function getText({
text: string; text: string;
fontSize?: string | number; fontSize?: string | number;
color?: string; color?: string;
zIndex?: number;
verticalAlign?: VerticalAlign; verticalAlign?: VerticalAlign;
horizontalAlign?: HorizontalAlign; horizontalAlign?: HorizontalAlign;
pointToProjection: UsePointToProjectionResult; pointToProjection: UsePointToProjectionResult;
...@@ -53,9 +56,15 @@ export default function getText({ ...@@ -53,9 +56,15 @@ export default function getText({
} }
const textCoords = pointToProjection({ x: textX, y: textY }); const textCoords = pointToProjection({ x: textX, y: textY });
const textFeature = new Feature({ geometry: new Point(textCoords) });
const textStyle = new Style({ const textStyle = new Style({
geometry: (feature: FeatureLike): Geometry | RenderFeature | undefined => {
const geometry = feature.getGeometry();
if (geometry && geometry.getType() === 'MultiPolygon') {
return (geometry as MultiPolygon).getPolygon(0).getInteriorPoint();
}
return undefined;
},
text: new Text({ text: new Text({
text, text,
font: `bold ${fontSize}px Arial`, font: `bold ${fontSize}px Arial`,
...@@ -66,8 +75,8 @@ export default function getText({ ...@@ -66,8 +75,8 @@ export default function getText({
textAlign: 'center', textAlign: 'center',
textBaseline: 'middle', textBaseline: 'middle',
}), }),
zIndex,
}); });
textFeature.setStyle(textStyle);
return { textCoords, textStyle }; return { textCoords, textStyle };
} }
import { z } from 'zod';
import { colorSchema } from '@/models/colorSchema';
export const modelElementModificationSchema = z.object({
id: z.number().int().positive(),
idModificationResidue: z.string(),
name: z.string(),
x: z.number(),
y: z.number(),
z: z.number(),
width: z.number(),
height: z.number(),
species: z.number(),
borderColor: colorSchema,
fillColor: colorSchema,
fontSize: z.number(),
state: z.string().nullable().optional(),
stateAbbreviation: z.string().nullable().optional(),
direction: z.enum(['RIGHT', 'LEFT']).optional(),
active: z.boolean().optional(),
sboTerm: z.string(),
size: z.number(),
elementId: z.string(),
});
...@@ -2,6 +2,7 @@ import { z } from 'zod'; ...@@ -2,6 +2,7 @@ import { z } from 'zod';
import { colorSchema } from '@/models/colorSchema'; import { colorSchema } from '@/models/colorSchema';
import { referenceSchema } from '@/models/referenceSchema'; import { referenceSchema } from '@/models/referenceSchema';
import { submodelSchema } from '@/models/submodelSchema'; import { submodelSchema } from '@/models/submodelSchema';
import { modelElementModificationSchema } from '@/models/modelElementModificationSchema';
import { glyphSchema } from '@/models/glyphSchema'; import { glyphSchema } from '@/models/glyphSchema';
export const modelElementSchema = z.object({ export const modelElementSchema = z.object({
...@@ -48,4 +49,5 @@ export const modelElementSchema = z.object({ ...@@ -48,4 +49,5 @@ export const modelElementSchema = z.object({
substanceUnits: z.boolean().nullable().optional(), substanceUnits: z.boolean().nullable().optional(),
references: z.array(referenceSchema), references: z.array(referenceSchema),
sboTerm: z.string(), sboTerm: z.string(),
modificationResidues: z.array(modelElementModificationSchema).optional(),
}); });
...@@ -68,6 +68,7 @@ import { oauthSchema } from '@/models/oauthSchema'; ...@@ -68,6 +68,7 @@ import { oauthSchema } from '@/models/oauthSchema';
import { bioShapeSchema } from '@/models/bioShapeSchema'; import { bioShapeSchema } from '@/models/bioShapeSchema';
import { shapeSchema } from '@/models/shapeSchema'; import { shapeSchema } from '@/models/shapeSchema';
import { modelElementsSchema } from '@/models/modelElementsSchema'; import { modelElementsSchema } from '@/models/modelElementsSchema';
import { modelElementModificationSchema } from '@/models/modelElementModificationSchema';
export type Project = z.infer<typeof projectSchema>; export type Project = z.infer<typeof projectSchema>;
export type OverviewImageView = z.infer<typeof overviewImageView>; export type OverviewImageView = z.infer<typeof overviewImageView>;
...@@ -78,6 +79,7 @@ export type MapModel = z.infer<typeof mapModelSchema>; ...@@ -78,6 +79,7 @@ export type MapModel = z.infer<typeof mapModelSchema>;
export type BioShape = z.infer<typeof bioShapeSchema>; export type BioShape = z.infer<typeof bioShapeSchema>;
export type ModelElements = z.infer<typeof modelElementsSchema>; export type ModelElements = z.infer<typeof modelElementsSchema>;
export type Shape = z.infer<typeof shapeSchema>; export type Shape = z.infer<typeof shapeSchema>;
export type Modification = z.infer<typeof modelElementModificationSchema>;
export type MapOverlay = z.infer<typeof mapOverlay>; export type MapOverlay = z.infer<typeof mapOverlay>;
export type MapBackground = z.infer<typeof mapBackground>; export type MapBackground = z.infer<typeof mapBackground>;
export type Organism = z.infer<typeof organism>; export type Organism = z.infer<typeof organism>;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment