UNPKG

romgrk-2d-geometry

Version:

Javascript library for 2d geometry

290 lines (277 loc) 13.7 kB
/** * Created by Alex Bol on 9/8/2017. */ 'use strict'; import { expect } from 'chai'; import Flatten from '../../index'; import {Point, Vector, Circle, Line, Segment, Arc, Box, Polygon, Edge, Face, Ray} from '../../index'; import {point, vector, circle, line, segment, arc, ray} from '../../index'; describe('#Flatten.Segment', function() { it('May create new instance of Segment', function () { let segment = new Segment(); expect(segment).to.be.an.instanceof(Segment); }); it('Constructor Segment(ps, pe) creates new instance of Segment', function () { let ps = new Point(1,1); let pe = new Point(2,3); let segment = new Segment(ps, pe); expect(segment.start).to.deep.equal({x:1, y:1}); expect(segment.end).to.deep.equal({x:2, y:3}); }); it('May construct segment when second point is omitted', function () { let ps = new Point(10,10); let segment = new Segment(ps); expect(segment.start).to.deep.equal({x:10, y:10}); expect(segment.end).to.deep.equal({x:0, y:0}); }); it('May constructor by array [4] ', function () { let ps = new Point(1,1); let pe = new Point(2,3); let segment = new Segment([ps.x,ps.y,pe.x,pe.y]); expect(segment.start).to.deep.equal(ps); expect(segment.end).to.deep.equal(pe); }); it('New segment may be constructed by function call', function() { expect(segment(point(1,1), point(2,3))).to.deep.equal(new Segment(new Point(1,1), new Point(2,3))); }); it('Constructor with illegal parameters throw error', function() { let fn = function () {new Segment([1,2,3])}; expect(fn).to.throw(ReferenceError); }); it('Method clone copy to a new instance of Segment', function () { let ps = new Point(1,1); let pe = new Point(2,3); let segment = new Segment(ps, pe); expect(segment.clone()).to.deep.equal(segment); }); it('Method length returns length of segment', function () { let ps = new Point(1,1); let pe = new Point(5,4); let segment = new Segment(ps, pe); expect(segment.length).to.equal(5.0); }); it('Method box returns bounding box of segment', function () { let ps = new Point(1,1); let pe = new Point(5,4); let segment = new Segment(ps, pe); expect(segment.box).to.deep.equal({xmin:1, ymin:1, xmax:5, ymax:4}); }); it('Method slope returns slope of segment', function () { let ps = new Point(1,1); let pe = new Point(5,5); let segment = new Segment(ps, pe); expect(segment.slope).to.equal(Math.PI/4); }); it('Method contains returns true if point belongs to segment', function () { let ps = new Point(-2,2); let pe = new Point(2,2); let segment = new Segment(ps, pe); let pt = new Point(1,2); expect(segment.contains(pt)).to.equal(true); }); it('Method tangentInStart and tangentInEnd returns vector [ps pe] and [pe, ps]', function () { let ps = new Point(5,1); let pe = new Point(5,5); let segment = new Segment(ps, pe); expect(segment.tangentInStart()).to.deep.equal(vector(0,1)); expect(segment.tangentInEnd()).to.deep.equal(vector(0,-1)); }); it('Calculates middle point', function() { let ps = new Point(-2,-2); let pe = new Point(2,2); let segment = new Segment(ps, pe); expect(segment.middle()).to.deep.equal({x:0,y:0}); }); it('Can translate segment by given vector', function() { let seg = segment(0,0,3,3); let v = vector(-1,-1); let seg_t = segment(-1,-1,2,2); expect(seg.translate(v)).to.deep.equal(seg_t); }); it('Can rotate by angle around center of bounding box', function() { let seg = segment(0,0,6,0); let seg_plus_pi_2 = segment(3,-3,3,3); let seg_minus_pi_2 = segment(3,3,3,-3); let center = seg.box.center; expect(seg.rotate(Math.PI/2, center).equalTo(seg_plus_pi_2)).to.be.true expect(seg.rotate(-Math.PI/2, center).equalTo(seg_minus_pi_2)).to.be.true }); it('Can rotate by angle around given point', function() { let seg = segment(1,1,3,3); let seg_plus_pi_2 = segment(1,1,-1,3); let seg_minus_pi_2 = segment(1,1,3,-1); expect(seg.rotate(Math.PI/2,seg.start).equalTo(seg_plus_pi_2)).to.be.true expect(seg.rotate(-Math.PI/2,seg.start).equalTo(seg_minus_pi_2)).to.be.true }); it('Method svg() without parameters creates svg string with default attributes', function() { let seg = new Segment(point(-2,2), point(2,2)); let svg = seg.svg(); expect(svg.search("stroke")).to.not.equal(-1); }) it('Method svg() with extra parameters may add additional attributes', function() { let seg = new Segment(point(-2,2), point(2,2)); let svg = seg.svg({id:"123",className:"name"}); expect(svg.search("stroke")).to.not.equal(-1); expect(svg.search("id")).to.not.equal(-1); expect(svg.search("class")).to.not.equal(-1); }) describe('#Flatten.Segment.Intersect', function() { it('Intersection with Segment - not parallel segments case (one point)', function () { let segment1 = new Segment(new Point(0,0), new Point(2,2)); let segment2 = new Segment(new Point(0,2), new Point(2,0)); expect(segment1.intersect(segment2).length).to.equal(1); expect(segment1.intersect(segment2)[0]).to.deep.equal({x:1, y:1}); }); it('Intersection with Segment - overlapping segments case (two points)', function () { let segment1 = new Segment(new Point(0,0), new Point(2,2)); let segment2 = new Segment(new Point(3,3), new Point(1,1)); expect(segment1.intersect(segment2).length).to.equal(2); expect(segment1.intersect(segment2)[0]).to.deep.equal({x:2, y:2}); expect(segment1.intersect(segment2)[1]).to.deep.equal({x:1, y:1}); }); it('Intersection with Segment - boxes intersecting, segments not intersecting', function () { let segment1 = new Segment(new Point(0,0), new Point(2,2)); let segment2 = new Segment(new Point(0.5,1.5), new Point(-2,-4)); expect(segment1.box.intersect(segment2.box)).to.equal(true); expect(segment1.intersect(segment2).length).to.equal(0); }); it('Intersection with Segment - boxes not intersecting, quick reject', function () { let segment1 = new Segment(new Point(0,0), new Point(2,2)); let segment2 = new Segment(new Point(-0.5,2.5), new Point(-2,-4)); expect(segment1.box.notIntersect(segment2.box)).to.equal(true); expect(segment1.intersect(segment2).length).to.equal(0); }); it('Intersection with Line - not parallel segments case (one point)', function () { let segment = new Segment(new Point(0,0), new Point(2,2)); let line = new Line(new Point(0,2), new Point(2,0)); expect(segment.intersect(line).length).to.equal(1); expect(segment.intersect(line)[0]).to.deep.equal({x:1, y:1}); }); it('Intersection with Line - segment lays on line case (two points)', function () { let segment = new Segment(0,0,2,2); let line = new Line(new Point(3,3), new Point(1,1)); expect(segment.intersect(line).length).to.equal(2); expect(segment.intersect(line)[0]).to.deep.equal({x:0, y:0}); expect(segment.intersect(line)[1]).to.deep.equal({x:2, y:2}); }); it('Intersection with Circle', function () { let segment = new Segment(0,0,2,2); let circle = new Circle(new Point(0,0), 1); let ip_expected = new Point(Math.sqrt(2)/2, Math.sqrt(2)/2); expect(segment.intersect(circle).length).to.equal(1); expect(segment.intersect(circle)[0].equalTo(ip_expected)).to.equal(true); }); it('Intersection with Circle - case of tangent', function () { let segment = new Segment(-2,2,2,2); let circle = new Circle(new Point(0,0), 2); let ip_expected = new Point(0, 2); expect(segment.intersect(circle).length).to.equal(1); expect(segment.intersect(circle)[0].equalTo(ip_expected)).to.equal(true); }); it('Intersection with Polygon', function () { let segment = new Segment(150,-20,150,60); let points = [ point(100, 20), point(200, 20), point(200, 40), point(100, 40) ]; let poly = new Polygon(); let face = poly.addFace(points); let ip_expected = new Point(0, 2); let ip = segment.intersect(poly); expect(ip.length).to.equal(2); expect(ip[0].equalTo(point(150,20))).to.be.true; expect(ip[1].equalTo(point(150,40))).to.be.true; }); it('Intersection with Box', function () { let segment = new Segment(150,-20,150,60); let points = [ point(100, 20), point(200, 20), point(200, 40), point(100, 40) ]; let poly = new Polygon(); let face = poly.addFace(points); let ip_expected = new Point(0, 2); let ip = segment.intersect(poly.box); expect(ip.length).to.equal(2); expect(ip[0].equalTo(point(150,20))).to.be.true; expect(ip[1].equalTo(point(150,40))).to.be.true; }); it("Intersection between two very close lines returns zero intersections (#99)", () => { const s1 = segment([34.35, 36.557426400375626, 25.4, 36.557426400375626]); const s2 = segment([25.4, 36.55742640037563, 31.25, 36.55742640037563]); const ip = s1.intersect(s2); expect(ip.length).to.equal(0); const [dist, shortest_segment] = s1.distanceTo(s2); }) }); describe('#Flatten.Segment.DistanceTo', function() { it('Distance to Segment Case 1 Intersected Segments', function () { let segment1 = new Segment(new Point(0, 0), new Point(2, 2)); let segment2 = new Segment(new Point(0, 2), new Point(2, 0)); expect(segment1.distanceTo(segment2)[0]).to.equal(0); }); it('Distance to Segment Case 2 Not Intersected Segments', function () { let segment1 = new Segment(new Point(0, 0), new Point(2, 2)); let segment2 = new Segment(new Point(1, 0), new Point(4, 0)); let [dist, ...rest] = segment1.distanceTo(segment2); expect(Flatten.Utils.EQ(dist,Math.sqrt(2)/2)).to.be.true; }); it('Distance to Line', function() { let seg = segment(1,3,4,6); let l = line(point(-1,1),vector(0,-1)); expect(seg.distanceTo(l)[0]).to.equal(2); }) it('Distance to Circle Case 1 Intersection - touching', function () { let segment = new Segment(point(-4, 2), point(4, 2)); let circle = new Circle(point(0,0),2); expect(segment.distanceTo(circle)[0]).to.equal(0); }); it('Distance to Circle Case 1 Intersection - two points', function () { let segment = new Segment(point(-4, 2), point(4, 2)); let circle = new Circle(point(0,0),3); expect(segment.distanceTo(circle)[0]).to.equal(0); }); it('Distance to Circle Case 1 Intersection - one points', function () { let segment = new Segment(point(0, 2), point(4, 2)); let circle = new Circle(point(0,0),3); expect(segment.distanceTo(circle)[0]).to.equal(0); }); it('Distance to Circle Case 2 Projection', function () { let segment = new Segment(point(-4, 4), point(4, 4)); let circle = new Circle(point(0,0),2); expect(segment.distanceTo(circle)[0]).to.equal(2); }); it('Distance to Circle Case 3 End point out of the circle', function () { let segment = new Segment(point(2,2), point(4,2)); let circle = new Circle(point(0,0),2); expect(segment.distanceTo(circle)[0]).to.equal(2*Math.sqrt(2)-2); }); it('Distance to Circle Case 3 End point inside the circle', function () { let segment = new Segment(point(-1,1), point(1,1)); let circle = new Circle(point(0,0),2); expect(segment.distanceTo(circle)[0]).to.equal(2 - Math.sqrt(2)); }); }); describe('#Flatten.Segment.pointAtLength', function () { it('gets the point at specific length', function () { let segment = new Segment(point(-1,1), point(1,1)) expect(segment.length).to.equal(2) expect(segment.pointAtLength(1).x).to.equal(0) expect(segment.pointAtLength(0).x).to.equal(-1) expect(segment.pointAtLength(2).x).to.equal(1) expect(segment.pointAtLength(0.5).x).to.equal(-0.5) }); it('points at specific length is on segment', function () { let segment = new Segment(point(-12,4), point(30, -2)) let length = segment.length for (let i = 0; i < 33; i++) { let point = segment.pointAtLength(i / 33 * length) expect(segment.contains(point)).to.be.true } }); }); });