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

refactor(vector-map): add support for relativeHeight and relativeWidth for ellipses

parent d2740426
No related branches found
No related tags found
1 merge request!276refactor(vector-map): add support for relativeHeight and relativeWidth for ellipses
Pipeline #96829 passed
Showing
with 119 additions and 172 deletions
import {
ColorObject,
EllipseCenter,
EllipseRadius,
ShapeCurvePoint,
ShapePoint,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
import { Color, ShapeRelAbs, ShapeRelAbsBezierPoint } from '@/types/models';
export const WHITE_COLOR: ColorObject = {
export const WHITE_COLOR: Color = {
alpha: 255,
rgb: 16777215,
};
export const BLACK_COLOR: ColorObject = {
export const BLACK_COLOR: Color = {
alpha: 255,
rgb: -16777216,
};
export const COMPARTMENT_SQUARE_POINTS: Array<ShapePoint | ShapeCurvePoint> = [
export const COMPARTMENT_SQUARE_POINTS: Array<ShapeRelAbs | ShapeRelAbsBezierPoint> = [
{
type: 'REL_ABS_POINT',
absoluteX: 10.0,
......@@ -148,7 +142,7 @@ export const COMPARTMENT_SQUARE_POINTS: Array<ShapePoint | ShapeCurvePoint> = [
},
];
export const COMPARTMENT_CIRCLE_CENTER: EllipseCenter = {
export const COMPARTMENT_CIRCLE_CENTER: ShapeRelAbs = {
type: 'REL_ABS_POINT',
absoluteX: 0.0,
absoluteY: 0.0,
......@@ -158,10 +152,12 @@ export const COMPARTMENT_CIRCLE_CENTER: EllipseCenter = {
relativeWidthForY: null,
};
export const COMPARTMENT_CIRCLE_RADIUS: EllipseRadius = {
export const COMPARTMENT_CIRCLE_RADIUS: ShapeRelAbs = {
type: 'REL_ABS_RADIUS',
absoluteX: 0.0,
absoluteY: 0.0,
relativeX: 50.0,
relativeY: 50.0,
relativeHeightForX: null,
relativeWidthForY: null,
};
......@@ -8,58 +8,3 @@ export type MapConfig = {
export type VerticalAlign = 'TOP' | 'MIDDLE' | 'BOTTOM';
export type HorizontalAlign = 'LEFT' | 'RIGHT' | 'CENTER' | 'END' | 'START';
export type ColorObject = {
alpha: number;
rgb: number;
};
export type ShapePoint = {
type: string;
absoluteX: number;
absoluteY: number;
relativeX: number;
relativeY: number;
relativeHeightForX: number | null;
relativeWidthForY: number | null;
};
export type ShapeCurvePoint = {
type: string;
absoluteX1: number;
absoluteY1: number;
relativeX1: number;
relativeY1: number;
relativeHeightForX1: number | null;
relativeWidthForY1: number | null;
absoluteX2: number;
absoluteY2: number;
relativeX2: number;
relativeY2: number;
relativeHeightForX2: number | null;
relativeWidthForY2: number | null;
absoluteX3: number;
absoluteY3: number;
relativeX3: number;
relativeY3: number;
relativeHeightForX3: number | null;
relativeWidthForY3: number | null;
};
export type EllipseCenter = {
type: string;
absoluteX: number;
absoluteY: number;
relativeX: number;
relativeY: number;
relativeHeightForX: number | null;
relativeWidthForY: number | null;
};
export type EllipseRadius = {
type: string;
absoluteX: number;
absoluteY: number;
relativeX: number;
relativeY: number;
};
......@@ -2,7 +2,7 @@
import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX';
import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { ShapeCurvePoint } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
import { ShapeRelAbsBezierPoint } from '@/types/models';
import getCurveCoords from './getCurveCoords';
jest.mock('./getCoordsX');
......@@ -21,8 +21,8 @@ describe('getCurveCoords', () => {
const height = 100;
const width = 200;
const point: ShapeCurvePoint = {
type: 'REL_ABS_POINT',
const point: ShapeRelAbsBezierPoint = {
type: 'REL_ABS_BEZIER_POINT',
absoluteX1: 10,
relativeX1: 5,
relativeHeightForX1: 2,
......
......@@ -2,7 +2,7 @@ import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { Coordinate } from 'ol/coordinate';
import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX';
import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY';
import { ShapeCurvePoint } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
import { ShapeRelAbsBezierPoint } from '@/types/models';
export default function getCurveCoords({
x,
......@@ -14,7 +14,7 @@ export default function getCurveCoords({
}: {
x: number;
y: number;
point: ShapeCurvePoint;
point: ShapeRelAbsBezierPoint;
height: number;
width: number;
pointToProjection: UsePointToProjectionResult;
......
......@@ -2,6 +2,7 @@
import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX';
import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { ShapeRelAbs } from '@/types/models';
import getEllipseCoords from './getEllipseCoords';
jest.mock('./getCoordsX');
......@@ -20,21 +21,23 @@ describe('getEllipseCoords', () => {
const height = 100;
const width = 200;
const center = {
type: 'center',
type: 'REL_ABS_POINT',
absoluteX: 15,
absoluteY: 25,
relativeX: 5,
relativeY: 10,
relativeHeightForX: null,
relativeWidthForY: null,
};
} as ShapeRelAbs;
const radius = {
type: 'radius',
type: 'REL_ABS_POINT',
absoluteX: 30,
absoluteY: 40,
relativeX: 10,
relativeY: 15,
};
relativeHeightForX: null,
relativeWidthForY: null,
} as ShapeRelAbs;
const points = 4;
(getCoordsX as jest.Mock).mockReturnValue(35);
......
......@@ -3,10 +3,7 @@ import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/
import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY';
import { Coordinate } from 'ol/coordinate';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import {
EllipseCenter,
EllipseRadius,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
import { ShapeRelAbs } from '@/types/models';
export default function getEllipseCoords({
x,
......@@ -20,8 +17,8 @@ export default function getEllipseCoords({
}: {
x: number;
y: number;
center?: EllipseCenter;
radius?: EllipseRadius;
center?: ShapeRelAbs;
radius?: ShapeRelAbs;
height: number;
width: number;
pointToProjection: UsePointToProjectionResult;
......@@ -50,8 +47,14 @@ export default function getEllipseCoords({
);
}
if (radius) {
radiusX = radius.absoluteX + (radius.relativeX * width) / 100;
radiusY = radius.absoluteY + (radius.relativeY * height) / 100;
radiusX =
radius.absoluteX +
(radius.relativeX * width) / 100 +
(height * (radius.relativeHeightForX || 0)) / 100;
radiusY =
radius.absoluteY +
(radius.relativeY * height) / 100 +
(width * (radius.relativeWidthForY || 0)) / 100;
}
let angle;
let coordsX;
......
......@@ -3,10 +3,7 @@ import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/
import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY';
import getCurveCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords';
import getBezierCurve from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getBezierCurve';
import {
ShapePoint,
ShapeCurvePoint,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
import { ShapeRelAbs, ShapeRelAbsBezierPoint } from '@/types/models';
import getPolygonCoords from './getPolygonCoords';
jest.mock('./getCoordsX');
......@@ -27,7 +24,7 @@ describe('getPolygonCoords', () => {
const height = 100;
const width = 200;
const points: Array<ShapePoint | ShapeCurvePoint> = [
const points: Array<ShapeRelAbs | ShapeRelAbsBezierPoint> = [
{
type: 'REL_ABS_POINT',
absoluteX: 0,
......@@ -75,7 +72,7 @@ describe('getPolygonCoords', () => {
const height = 100;
const width = 200;
const points: Array<ShapePoint | ShapeCurvePoint> = [
const points: Array<ShapeRelAbs | ShapeRelAbsBezierPoint> = [
{
type: 'REL_ABS_POINT',
absoluteX: 0,
......@@ -86,7 +83,7 @@ describe('getPolygonCoords', () => {
relativeWidthForY: null,
},
{
type: 'REL_ABS_POINT',
type: 'REL_ABS_BEZIER_POINT',
absoluteX1: 50,
absoluteY1: 50,
relativeX1: 10,
......
......@@ -5,10 +5,7 @@ import getBezierCurve from '@/components/Map/MapViewer/MapViewerVector/utils/sha
import getCoordsX from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsX';
import getCoordsY from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCoordsY';
import getCurveCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getCurveCoords';
import {
ShapeCurvePoint,
ShapePoint,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
import { ShapeRelAbs, ShapeRelAbsBezierPoint } from '@/types/models';
export default function getPolygonCoords({
points,
......@@ -18,7 +15,7 @@ export default function getPolygonCoords({
width,
pointToProjection,
}: {
points: Array<ShapePoint | ShapeCurvePoint>;
points: Array<ShapeRelAbs | ShapeRelAbsBezierPoint>;
x: number;
y: number;
height: number;
......
......@@ -5,7 +5,6 @@ import Feature, { FeatureLike } from 'ol/Feature';
import { MultiPolygon } from 'ol/geom';
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import {
ColorObject,
HorizontalAlign,
VerticalAlign,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
......@@ -13,6 +12,7 @@ import { MapInstance } from '@/types/map';
import getTextStyle from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextStyle';
import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex';
import getTextCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/text/getTextCoords';
import { Color } from '@/types/models';
export interface BaseMapElementProps {
x: number;
......@@ -26,11 +26,11 @@ export interface BaseMapElementProps {
nameY: number;
nameWidth: number;
nameHeight: number;
fontColor: ColorObject;
fontColor: Color;
nameVerticalAlign: VerticalAlign;
nameHorizontalAlign: HorizontalAlign;
fillColor: ColorObject;
borderColor: ColorObject;
fillColor: Color;
borderColor: Color;
pointToProjection: UsePointToProjectionResult;
}
......@@ -57,15 +57,15 @@ export default abstract class BaseMultiPolygon {
nameHeight: number;
fontColor: ColorObject;
fontColor: Color;
nameVerticalAlign: VerticalAlign;
nameHorizontalAlign: HorizontalAlign;
fillColor: ColorObject;
fillColor: Color;
borderColor: ColorObject;
borderColor: Color;
polygons: Array<Polygon> = [];
......
/* eslint-disable no-magic-numbers */
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import {
ColorObject,
HorizontalAlign,
VerticalAlign,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
......@@ -13,6 +12,7 @@ import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/sty
import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex';
import getStroke from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getStroke';
import { MapInstance } from '@/types/map';
import { Color } from '@/types/models';
export interface CompartmentProps {
x: number;
......@@ -29,11 +29,11 @@ export interface CompartmentProps {
nameY: number;
nameWidth: number;
nameHeight: number;
fontColor: ColorObject;
fontColor: Color;
nameVerticalAlign: VerticalAlign;
nameHorizontalAlign: HorizontalAlign;
fillColor: ColorObject;
borderColor: ColorObject;
fillColor: Color;
borderColor: Color;
pointToProjection: UsePointToProjectionResult;
mapInstance: MapInstance;
}
......
......@@ -2,7 +2,6 @@
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { MapInstance } from '@/types/map';
import {
ColorObject,
HorizontalAlign,
VerticalAlign,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
......@@ -14,6 +13,7 @@ import {
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
import getEllipseCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getEllipseCoords';
import Compartment from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment';
import { Color } from '@/types/models';
export type CompartmentCircleProps = {
x: number;
......@@ -21,9 +21,9 @@ export type CompartmentCircleProps = {
width: number;
height: number;
zIndex: number;
fillColor?: ColorObject;
borderColor?: ColorObject;
fontColor?: ColorObject;
fillColor?: Color;
borderColor?: Color;
fontColor?: Color;
innerWidth?: number;
outerWidth?: number;
thickness?: number;
......
......@@ -2,7 +2,6 @@
import { UsePointToProjectionResult } from '@/utils/map/usePointToProjection';
import { MapInstance } from '@/types/map';
import {
ColorObject,
HorizontalAlign,
VerticalAlign,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
......@@ -13,6 +12,7 @@ import {
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
import getPolygonCoords from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/coords/getPolygonCoords';
import Compartment from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/Compartment';
import { Color } from '@/types/models';
export type CompartmentSquareProps = {
x: number;
......@@ -20,9 +20,9 @@ export type CompartmentSquareProps = {
width: number;
height: number;
zIndex: number;
fillColor?: ColorObject;
borderColor?: ColorObject;
fontColor?: ColorObject;
fillColor?: Color;
borderColor?: Color;
fontColor?: Color;
innerWidth?: number;
outerWidth?: number;
thickness?: number;
......
......@@ -6,10 +6,9 @@ import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/sty
import Polygon from 'ol/geom/Polygon';
import getMultiPolygon from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/elements/getMultiPolygon';
import { rgbToHex } from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/rgbToHex';
import { BioShape, LineType, Modification, Shape } from '@/types/models';
import { BioShape, Color, LineType, Modification, Shape } from '@/types/models';
import { MapInstance } from '@/types/map';
import {
ColorObject,
HorizontalAlign,
VerticalAlign,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
......@@ -27,9 +26,9 @@ export type MapElementProps = {
width: number;
height: number;
zIndex: number;
fillColor?: ColorObject;
borderColor?: ColorObject;
fontColor?: ColorObject;
fillColor?: Color;
borderColor?: Color;
fontColor?: Color;
lineWidth?: number;
lineType?: string;
text?: string;
......@@ -129,7 +128,6 @@ export default class MapElement extends BaseMultiPolygon {
}
protected createPolygons(): void {
let multiPolygonModifications: Array<Polygon> = [];
this.modifications.forEach(modification => {
if (modification.state === null) {
return;
......@@ -139,41 +137,7 @@ export default class MapElement extends BaseMultiPolygon {
if (!shape) {
return;
}
multiPolygonModifications = getMultiPolygon({
x: modification.x,
y: modification.y,
width: modification.width,
height: modification.height,
shapes: shape.shapes,
pointToProjection: this.pointToProjection,
mirror: modification.direction && modification.direction === 'RIGHT',
});
this.polygons.push(...multiPolygonModifications);
multiPolygonModifications.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}pt Arial`,
textAlign: 'center',
textBaseline: 'middle',
fill: getFill({ color: '#000' }),
overflow: true,
}),
);
this.polygonsTexts.push(modificationText);
}
this.styles.push(modificationStyle);
});
this.drawModification(modification, shape.shapes);
});
if (this.lineType) {
......@@ -193,6 +157,44 @@ export default class MapElement extends BaseMultiPolygon {
}
}
drawModification(modification: Modification, shapes: Array<Shape>): void {
const multiPolygonModification = getMultiPolygon({
x: modification.x,
y: modification.y,
width: modification.width,
height: modification.height,
shapes,
pointToProjection: this.pointToProjection,
mirror: modification.direction && modification.direction === 'RIGHT',
});
this.polygons.push(...multiPolygonModification);
multiPolygonModification.forEach((polygon: 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}pt Arial`,
textAlign: 'center',
textBaseline: 'middle',
fill: getFill({ color: '#000' }),
overflow: true,
}),
);
this.polygonsTexts.push(modificationText);
}
this.styles.push(modificationStyle);
});
}
drawActiveBorder(homodimerShift: number, homodimerOffset: number): void {
const activityBorderElement = getMultiPolygon({
x: this.x + homodimerShift - 5,
......
......@@ -115,6 +115,8 @@ describe('getMultiPolygon', () => {
absoluteY: -7.0,
relativeX: 50.0,
relativeY: 50.0,
relativeHeightForX: null,
relativeWidthForY: null,
},
},
];
......@@ -171,6 +173,8 @@ describe('getMultiPolygon', () => {
absoluteY: -7.0,
relativeX: 50.0,
relativeY: 50.0,
relativeHeightForX: null,
relativeWidthForY: null,
},
},
{
......
......@@ -7,8 +7,8 @@ import {
BLACK_COLOR,
WHITE_COLOR,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.constants';
import { ColorObject } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
import getFill from '@/components/Map/MapViewer/MapViewerVector/utils/shapes/style/getFill';
import { Color } from '@/types/models';
export default function getStyle({
geometry,
......@@ -19,8 +19,8 @@ export default function getStyle({
zIndex = 1,
}: {
geometry?: Geometry;
borderColor?: ColorObject;
fillColor?: ColorObject;
borderColor?: Color;
fillColor?: Color;
lineWidth?: number;
lineDash?: Array<number>;
zIndex?: number;
......
import { ColorObject } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
import { Color } from '@/types/models';
import { rgbToHex } from './rgbToHex';
describe('rgbToHex', () => {
it('should correctly convert RGB and alpha values to hex', () => {
const color: ColorObject = {
const color: Color = {
rgb: -16222216,
alpha: 255,
};
......@@ -14,7 +14,7 @@ describe('rgbToHex', () => {
});
it('should correctly handle alpha values less than 255', () => {
const color: ColorObject = {
const color: Color = {
rgb: -16777216,
alpha: 128,
};
......
/* eslint-disable no-magic-numbers */
import { ColorObject } from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
export function rgbToHex(color: ColorObject): string {
import { Color } from '@/types/models';
export function rgbToHex(color: Color): string {
const positiveRgb = color.rgb < 0 ? color.rgb + 0x100000000 : color.rgb;
const hexRgb = positiveRgb.toString(16).slice(-6).padStart(6, '0').toUpperCase();
const hexAlpha = color.alpha.toString(16).padStart(2, '0').toUpperCase();
......
/* eslint-disable no-magic-numbers */
import {
ColorObject,
HorizontalAlign,
VerticalAlign,
} from '@/components/Map/MapViewer/MapViewerVector/MapViewerVector.types';
......@@ -13,6 +12,7 @@ import { FeatureLike } from 'ol/Feature';
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';
export interface TextProps {
x: number;
......@@ -22,7 +22,7 @@ export interface TextProps {
zIndex: number;
text: string;
fontSize: number;
fontColor: ColorObject;
fontColor: Color;
verticalAlign: VerticalAlign;
horizontalAlign: HorizontalAlign;
pointToProjection: UsePointToProjectionResult;
......
import { z } from 'zod';
import { shapeRelAbsPointSchema } from '@/models/shapeRelAbsPointSchema';
import { shapeRelAbsRadiusSchema } from '@/models/shapeRelAbsRadiusSchema';
import { shapeRelAbsSchema } from '@/models/shapeRelAbsSchema';
export const shapeEllipseSchema = z.object({
type: z.literal('ELLIPSE'),
center: shapeRelAbsPointSchema,
radius: shapeRelAbsRadiusSchema,
center: shapeRelAbsSchema,
radius: shapeRelAbsSchema,
});
import { z } from 'zod';
import { shapeRelAbsBezierPointSchema } from '@/models/shapeRelAbsBezierPointSchema';
import { shapeRelAbsPointSchema } from '@/models/shapeRelAbsPointSchema';
import { shapeRelAbsSchema } from '@/models/shapeRelAbsSchema';
export const shapePolygonSchema = z.object({
type: z.literal('POLYGON'),
points: z.array(z.union([shapeRelAbsPointSchema, shapeRelAbsBezierPointSchema])),
points: z.array(z.union([shapeRelAbsSchema, shapeRelAbsBezierPointSchema])),
});
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