import type { Writable } from "svelte/store"; export type Location = Object; // disambiguated (physical or online) library object export type Item = { title: String, MMS: String, Barcode: String, // String because of preceding 0 Publisher: String, _original: Object } // A movement of the object (Request in Alma Analytics) export type Movement = { nr: number, // unique identifier in the set source: Location, target: Location, item: Item, _original: Object // also contains additional request data (see requests.csv) d: String, // the svg path date: Date, }; export type Occurences = Map export interface Data { locations: Map, items: Map, movements: Movement[], occurences: Occurences } // An event to trigger drawing an Edge export type Motion = { duration: number, movement: Movement, } export type Log = { date: Date, title: String, description: String } // Type used by the scenes with all reactive Writables for drawable objects export type VizData = { drawn_motions: Writable, overlay_motions: Writable, events: Writable, current_item: Writable } export function get_path_d(movement: Movement) { const m = movement; // console.log(m) let sourceX, targetX, midX, dx, dy, angle; // This mess makes the arrows exactly perfect. // thanks to http://bl.ocks.org/curran/9b73eb564c1c8a3d8f3ab207de364bf4 if (m.source.x < m.target.x) { sourceX = m.source.x; targetX = m.target.x; } else if (m.target.x < m.source.x) { targetX = m.target.x; sourceX = m.source.x; } else if (m.target.isCircle) { targetX = sourceX = m.target.x; } else if (m.source.isCircle) { targetX = sourceX = m.source.x; } else { midX = (m.source.x + m.target.x) / 2; if (midX > m.target.x) { midX = m.target.x; } else if (midX > m.source.x) { midX = m.source.x; } else if (midX < m.target.x) { midX = m.target.x; } else if (midX < m.source.x) { midX = m.source.x; } targetX = sourceX = midX; } dx = targetX - sourceX; dy = m.target.y - m.source.y; angle = Math.atan2(dx, dy); var srcSize = 31; //_mapGraph.getSizeForNode(m.source); var tgtSize = 31; //_mapGraph.getSizeForNode(m.target); // Compute the line endpoint such that the arrow // it not in the center, but rather slightly out of it // use a small ofset for the Movemente to compensate roughly for the curve let m_sourceX = sourceX + Math.sin(angle + 0.5) * srcSize; let m_targetX = targetX - Math.sin(angle - 0.5) * tgtSize; let m_sourceY = m.source.y + Math.cos(angle + 0.5) * srcSize; let m_targetY = m.target.y - Math.cos(angle - 0.5) * tgtSize; // find radius of arc based on distance between points // add a jitter to spread out the lines when links are stacked const dr = Math.sqrt(dx * dx + dy * dy) * (0.7 + Math.random() * 0.5); // "M" + d.source.x + "," + d.source.y + "A" + dr + "," + dr + " 0 0,1 " + d.target.x + "," + d.target.y return `M ${m_sourceX},${m_sourceY} A ${dr},${dr} 0 0,1 ${m_targetX},${m_targetY}`; }