www.spaceplanner.app

Web client to the spaceplanner API
git clone git://jacobedwards.org/www.spaceplanner.app
Log | Files | Refs

commit f62b47d3498b7da0874dc7ace47016c8298ae290
parent cc8d7a70e87eedb960773248b5b30fadfa7bacf3
Author: Jacob R. Edwards <jacob@jacobedwards.org>
Date:   Thu, 22 Aug 2024 11:53:15 -0700

Add separate file for geometric math

Mostly left the existing math from main.js where it is (to be adapted
and moved over later), but extended SVG.Line to support the inside()
method aswell as a method called closestPoint which just gives you
the point on the line where the given point is, if any.

These will be necessary for future additions to the floorplan editor.

Diffstat:
Afiles/floorplans/floorplan/geometry.js | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mfiles/floorplans/floorplan/main.js | 24+-----------------------
2 files changed, 78 insertions(+), 23 deletions(-)

diff --git a/files/floorplans/floorplan/geometry.js b/files/floorplans/floorplan/geometry.js @@ -0,0 +1,77 @@ +import { default as SVG } from "/lib/github.com/svgdotjs/svg.js/svg.js" +import { Vector2 } from "/lib/github.com/ros2jsguy/threejs-math/math/Vector2.js" + +SVG.extend(SVG.Point, { + vec: function() { + return new Vector2(this.x, this.y) + } +}) + +SVG.extend(SVG.Shape, { + vec: function() { + return new Vector2(this.x(), this.y()) + } +}) + +SVG.extend(SVG.Line, { + vecs: function() { + let a = this.array() + let vecs = [] + for (let i in a) { + vecs.push(new Vector2(a[i][0], a[i][1])) + } + return vecs + }, + + /* + * Most of this copied from the svg.js math library, + * but I didn't particularly like the look of the + * library itself so I wrote equivilents here. + */ + segmentLengthSquared: function() { + let vecs = this.vecs() + return vecs[0].distanceToSquared(vecs[1]) + }, + + closestLinearInterpolation: function(p) { + let vecs = this.vecs() + let d = vecs[1].clone().sub(vecs[0]) + let x = p.clone().sub(vecs[0]).multiply(d) + return (x.x + x.y) / this.segmentLengthSquared() + }, + + interpolatedPoint: function(t) { + let vecs = this.vecs() + return vecs[0].lerp(vecs[1], t) + }, + + closestPoint: function(p) { + return this.interpolatedPoint( + Math.min(1, Math.max(0, this.closestLinearInterpolation(p))) + ) + }, + + whereIsPoint: function(x, y) { + let p = new Vector2(x, y) + let width = this.attr("stroke-width") ?? 1 + let closest = this.closestPoint(p) + + /* + * Note that this doesn't work very accurately for + * lines that aren't at 90 degree angles. Check out + * Harry Stevens's geometric library with the lineOnPoint + * function and the epsilon number + */ + let h = width / 2 + if (p.x > closest.x - h && p.x < closest.x + h && + p.y > closest.y - h && p.y < closest.y + h) { + return closest + } + return null + }, + + // This must use x and y to be compatible with Shape's inside() + inside: function(x, y) { + return this.whereIsPoint(x, y) != null ? true : false + } +}) diff --git a/files/floorplans/floorplan/main.js b/files/floorplans/floorplan/main.js @@ -4,29 +4,7 @@ import * as ui from "/lib/ui.js" import * as etc from "/lib/etc.js" import { FloorplanEditor as Editor } from "./editor.js" import { Vector2 } from "/lib/github.com/ros2jsguy/threejs-math/math/Vector2.js" - -SVG.extend(SVG.Point, { - vec: function() { - return new Vector2(this.x, this.y) - } -}) - -SVG.extend(SVG.Line, { - vecs: function() { - let a = this.array() - let vecs = [] - for (let i in a) { - vecs.push(new Vector2(a[i][0], a[i][1])) - } - return vecs - } -}) - -SVG.extend(SVG.Shape, { - vec: function() { - return new Vector2(this.x(), this.y()) - } -}) +import "./geometry.js" const messageTimeout = 4000 const movingAddTimeout = 250