UNPKG

flatten-js

Version:

Javascript library for 2d geometry

132 lines (110 loc) 3.75 kB
"use strict"; module.exports = function(Flatten) { let {Point, Segment, Line, Circle, Arc, Box, Vector} = Flatten; /** * Class representing a horizontal ray, used by ray shooting algorithm * @type {Ray} */ Flatten.Ray = class Ray { /** * Construct ray by setting start point * @param {Point} pt - start point */ constructor(...args) { this.pt = new Point(); if (args.length == 0) { return; } if (args.length == 1 && args[0] instanceof Point) { this.pt = args[0].clone(); return; } if (args.length == 2 && typeof(args[0]) == "number" && typeof(args[1]) == "number") { this.pt = new Point(args[0], args[1]); return; } throw Flatten.Errors.ILLEGAL_PARAMETERS; } /** * Returns copied instance of the ray object * @returns {Ray} */ clone() { return new Ray(this.pt); } /** * Returns half-infinite bounding box of the ray * @returns {Box} - bounding box */ get box() { return new Box( this.pt.x, this.pt.y, Number.POSITIVE_INFINITY, this.pt.y ) } /** * Return ray start point * @returns {Point} - ray start point */ get start() { return this.pt; } /** * Return ray normal vector (0,1) - horizontal ray * @returns {Vector} - ray normal vector */ get norm() { return new Vector(0,1); } /** * Returns array of intersection points between ray and segment or arc * @param {Segment|Arc} - Shape to intersect with ray * @returns {Array} array of intersection points */ intersect(shape) { if (shape instanceof Segment) { return this.intersectRay2Segment(this, shape); } if (shape instanceof Arc) { return this.intersectRay2Arc(this, shape); } } intersectRay2Segment(ray, segment) { let ip = []; if (ray.box.not_intersect(segment.box)) { return ip; } let line = new Line(ray.start, ray.norm); let ip_tmp = line.intersect(segment); for (let pt of ip_tmp) { if (Flatten.Utils.GE(pt.x, ray.start.x)) { ip.push(pt); } } /* If there were two intersection points between line and ray, and now there is exactly one left, it means ray starts between these points and there is another intersection point - start of the ray */ if (ip_tmp.length == 2 && ip.length == 1 && ray.start.on(line)) { ip.push(ray.start); } return ip; } intersectRay2Arc(ray, arc) { let ip = []; if (ray.box.not_intersect(arc.box)) { return ip; } let line = new Line(ray.start, ray.norm); let ip_tmp = line.intersect(arc); for (let pt of ip_tmp) { if (Flatten.Utils.GE(pt.x, ray.start.x)) { ip.push(pt); } } return ip; } }; Flatten.ray = (...args) => new Flatten.Ray(...args); };