Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 25 additions & 3 deletions client/src/components/geoJS/LayerManager.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import TimeLayer from "./layers/timeLayer";
import FreqLayer from "./layers/freqLayer";
import SpeciesLayer from "./layers/speciesLayer";
import SpeciesSequenceLayer from "./layers/speciesSequenceLayer";
import MeasureToolLayer from "./layers/measureToolLayer";
import { cloneDeep } from "lodash";
import useState from "@use/useState";
export default defineComponent({
Expand Down Expand Up @@ -63,6 +64,7 @@ export default defineComponent({
configuration,
colorScheme,
backgroundColor,
measuring,
} = useState();
const selectedAnnotationId: Ref<null | number> = ref(null);
const hoveredAnnotationId: Ref<null | number> = ref(null);
Expand All @@ -79,6 +81,7 @@ export default defineComponent({
let freqLayer: FreqLayer;
let speciesLayer: SpeciesLayer;
let speciesSequenceLayer: SpeciesSequenceLayer;
let measureToolLayer: MeasureToolLayer;
const displayError = ref(false);
const errorMsg = ref("");

Expand Down Expand Up @@ -510,6 +513,19 @@ export default defineComponent({
speciesLayer.spectroInfo = props.spectroInfo;
speciesLayer.setScaledDimensions(props.scaledWidth, props.scaledHeight);

if (!measureToolLayer) {
measureToolLayer = new MeasureToolLayer(props.geoViewerRef, event, props.spectroInfo, measuring.value);
measureToolLayer.setScaledDimensions(props.scaledWidth, props.scaledHeight);
}
measureToolLayer.redraw();
watch(measuring, () => {
if (measuring.value) {
measureToolLayer.enableDrawing();
} else {
measureToolLayer.disableDrawing();
}
});

timeLayer.setDisplaying({ pulse: configuration.value.display_pulse_annotations, sequence: configuration.value.display_sequence_annotations });
timeLayer.formatData(localAnnotations.value, sequenceAnnotations.value);
freqLayer.formatData(localAnnotations.value);
Expand Down Expand Up @@ -608,6 +624,10 @@ export default defineComponent({
);
sequenceAnnotationLayer.redraw();
}
if (measureToolLayer) {
measureToolLayer.setScaledDimensions(props.scaledWidth, props.scaledHeight);
measureToolLayer.redraw();
}
// Triggers the Axis redraw when zoomed in and the axis is at the bottom/top
legendLayer?.onPan();
});
Expand Down Expand Up @@ -642,7 +662,7 @@ export default defineComponent({
// convert rgb(0 0 0) to rgb(0, 0, 0)
backgroundColor.value = backgroundColor.value.replace(/rgb\((\d+)\s+(\d+)\s+(\d+)\)/, 'rgb($1, $2, $3)');
}

const backgroundRgbColor = d3.color(backgroundColor.value) as d3.RGBColor;
const redStops: number[] = [backgroundRgbColor.r / 255];
const greenStops: number[] = [backgroundRgbColor.g / 255];
Expand All @@ -669,11 +689,13 @@ export default defineComponent({
}
if (timeLayer) {
timeLayer.setTextColor(textColor);
}
}
if (speciesSequenceLayer) {
speciesSequenceLayer.setTextColor(textColor);
}

if (measureToolLayer) {
measureToolLayer.setTextColor(textColor);
}
}

watch([backgroundColor, colorScheme], updateColorFilter);
Expand Down
16 changes: 1 addition & 15 deletions client/src/components/geoJS/layers/freqLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,7 @@
import { SpectrogramAnnotation } from "../../../api/api";
import { SpectroInfo, spectroToGeoJSon } from "../geoJSUtils";
import BaseTextLayer from "./baseTextLayer";
import { LayerStyle } from "./types";

interface LineData {
line: GeoJSON.LineString;
thicker?: boolean;
grid?: boolean;
}

interface TextData {
text: string;
x: number;
y: number;
offsetY?: number;
offsetX?: number;
}
import { LayerStyle, LineData, TextData } from "./types";

export default class FreqLayer extends BaseTextLayer<TextData> {
lineData: LineData[];
Expand Down
221 changes: 221 additions & 0 deletions client/src/components/geoJS/layers/measureToolLayer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import geo, { GeoEvent } from 'geojs';
import { SpectroInfo } from '../geoJSUtils';
import { LayerStyle, LineData, TextData } from './types';
import BaseTextLayer from './baseTextLayer';

function _determineRulerColor(isDragging: boolean, isDarkMode: boolean) {
if (isDarkMode) {
return isDragging ? 'orange' : 'yellow';
}
return isDragging ? 'cyan' : 'blue';
}

export default class MeasureToolLayer extends BaseTextLayer<TextData> {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
frequencyRulerLayer: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
pointAnnotation: any;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
lineAnnotation: any;

rulerOn: boolean;
dragging: boolean;
yValue: number;

moveHandler: (e: GeoEvent) => void;
mousedownHandler: (e: GeoEvent) => void;
mouseupHandler: () => void;

constructor(
// eslint-disable-next-line @typescript-eslint/no-explicit-any
geoViewerRef: any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
event: (name: string, data: any) => void,
spectroInfo: SpectroInfo,
measuring?: boolean
) {
super(geoViewerRef, event, spectroInfo);

const textLayer = this.geoViewerRef.createLayer('feature', {
features: ['text']
});
this.textLayer = textLayer
.createFeature("text")
.text((data: TextData) => data.text)
.style(this.createTextStyle())
.position((data: TextData) => ({
x: data.x,
y: data.y,
}));

const frequencyRulerLayer = this.geoViewerRef.createLayer("feature", {
features: ['point', 'line'],
});
this.frequencyRulerLayer = frequencyRulerLayer;
this.rulerOn = false;
this.pointAnnotation= null;
this.lineAnnotation = null;
this.dragging = false;
this.yValue = 0;
this.color = 'white';

this.textStyle = this.createTextStyle();
this.rulerOn = measuring || false;
if (this.rulerOn) {
this.enableDrawing();
}

this.moveHandler = (e: GeoEvent) => {
if (e && this.dragging) {
this.updateRuler(e.mouse.geo.y);
}
};
this.mousedownHandler = (e: GeoEvent) => {
const gcs = this.geoViewerRef.displayToGcs(e.map);
const p = this.pointAnnotation.data()[0];
const dx = Math.abs(gcs.x - p.x);
const dy = Math.abs(gcs.y - p.y);
if (Math.sqrt(dx*dx + dy*dy) < 20 || dy < 10) {
this.geoViewerRef.interactor().addAction({
action: 'dragpoint',
name: 'drag point with mouse',
owner: 'MeasureToolLayer',
input: 'left',
});
this.dragging = true;
}
};
this.mouseupHandler = () => {
this.dragging = false;
this.geoViewerRef.interactor().removeAction(undefined, undefined, 'MeasureToolLayer');
this.updateRuler(this.yValue);
};
}

enableDrawing() {
this.rulerOn = true;
// Frequency ruler
this.lineAnnotation = this.frequencyRulerLayer.createFeature('line')
.data([[
{x: 0, y: this.yValue},
{x: this.spectroInfo.width, y: this.yValue},
]])
.style(this.createLineStyle());
this.pointAnnotation = this.frequencyRulerLayer.createFeature('point')
.data([{x: 0, y: this.yValue}])
.style(this.createPointStyle());
this.geoViewerRef.geoOn(geo.event.mousedown, this.mousedownHandler);
this.geoViewerRef.geoOn(geo.event.actionmove, this.moveHandler);
this.geoViewerRef.geoOn(geo.event.mouseup, this.mouseupHandler);
this.frequencyRulerLayer.draw();
this.updateRuler(this.yValue);
}

_getTextCoordinates(): { x: number, y: number } {
const bounds = this.geoViewerRef.bounds();
const startX = 0;
const endX = ((this.compressedView
? this.scaledWidth
: this.spectroInfo.width
) || this.spectroInfo.width);
const left = Math.max(startX, bounds.left);
const right = Math.min(endX, bounds.right);
return { x: (left + right) / 2, y: this.yValue };
}

updateRuler(newY: number) {
if (newY < 0) {
return;
}
this.yValue = newY;
const spectroWidth = this.compressedView ? this.scaledWidth : this.spectroInfo.width;
this.lineAnnotation
.data([[
{x: 0, y: this.yValue},
{x: (spectroWidth || this.spectroInfo.width), y: this.yValue},
]])
.style(this.createLineStyle());
this.pointAnnotation
.data([{x: 0, y: this.yValue}])
.style(this.createPointStyle());
this.frequencyRulerLayer.draw();
const height = Math.max(this.scaledHeight, this.spectroInfo.height);
const frequency = height - this.yValue >= 0
? ((height - newY) * (this.spectroInfo.high_freq - this.spectroInfo.low_freq)) / height / 1000 + this.spectroInfo.low_freq / 1000
: -1;
const textValue = `${frequency.toFixed(1)}KHz`;
const { x: textX, y: textY } = this._getTextCoordinates();
this.textData = [
{
text: textValue,
x: textX,
y: textY,
offsetY: 20,
},
];
this.textLayer.data(this.textData).draw();
}

disableDrawing() {
this.rulerOn = false;
this.textData = [];
this.textLayer.data(this.textData).draw();
this.clearRulerLayer();
this.geoViewerRef.geoOff(geo.event.mousedown, this.mousedownHandler);
this.geoViewerRef.geoOff(geo.event.mouseup, this.mouseupHandler);
this.geoViewerRef.geoOff(geo.event.actionmove, this.moveHandler);
}

clearRulerLayer() {
this.pointAnnotation.data([]);
this.lineAnnotation.data([]);
this.textLayer.data([]).draw();
this.frequencyRulerLayer.draw();
}

destroy() {
super.destroy();
this.textData = [];
if (this.frequencyRulerLayer) {
this.geoViewerRef.deleteLater(this.frequencyRulerLayer);
}
}

redraw() {
if (this.rulerOn) {
this.updateRuler(this.yValue);
}
super.redraw();
}

createTextStyle(): LayerStyle<TextData> {
return {
color: () => _determineRulerColor(this.dragging, this.color === 'white'),
offset: (data: TextData) => ({
x: data.offsetX || 0,
y: data.offsetY || 0,
}),
textAlign: 'center',
textScaled: this.textScaled,
textBaseline: 'bottom',
};
}

createPointStyle(): LayerStyle<LineData> {
return {
radius: 10,
fillColor: () => _determineRulerColor(this.dragging, this.color === 'white'),
strokeColor: () => _determineRulerColor(this.dragging, this.color === 'white'),
stroke: true,
strokeWidth: 5,
};
}

createLineStyle(): LayerStyle<LineData> {
return {
strokeColor: () => _determineRulerColor(this.dragging, this.color === 'white'),
strokeWidth: 2,
};
}

}
14 changes: 3 additions & 11 deletions client/src/components/geoJS/layers/rectangleLayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,8 @@
import geo, { GeoEvent } from "geojs";
import { SpectroInfo, spectroToGeoJSon } from "../geoJSUtils";
import { SpectrogramAnnotation } from "../../../api/api";
import { LayerStyle } from "./types";

interface RectGeoJSData {
id: number;
selected: boolean;
editing?: boolean;
polygon: GeoJSON.Polygon;
color?: string;
owned: boolean; // if the annotation is user owned
}
import { LayerStyle, RectGeoJSData } from "./types";


export default class RectangleLayer {
formattedData: RectGeoJSData[];
Expand Down Expand Up @@ -113,7 +105,7 @@ export default class RectangleLayer {

setScaledDimensions(newWidth: number, newHeight: number) {
this.scaledWidth = newWidth;
this.scaledHeight = newHeight;
this.scaledHeight = newHeight;
}

destroy() {
Expand Down
23 changes: 23 additions & 0 deletions client/src/components/geoJS/layers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,26 @@ export interface LayerStyle<D> {
[x: string]: unknown;
visible?: (data: D) => boolean;
}

export interface RectGeoJSData {
id: number;
selected: boolean;
editing?: boolean;
polygon: GeoJSON.Polygon;
color?: string;
owned: boolean; // if the annotation is user owned
}

export interface LineData {
line: GeoJSON.LineString;
thicker?: boolean;
grid?: boolean;
}

export interface TextData {
text: string;
x: number;
y: number;
offsetY?: number;
offsetX?: number;
}
Loading