直線・線分・ベクトル
直線
code: geometry.ts
/**
* 直線クラス
*/
export class LineModel {
points: Array<Point>;
constructor(pos1: Point, pos2: Point) {
}
/**
* ベクトル座標
*/
vector(): Point {
return this.points1.minus(this.points0); }
//直線に対する点の位置
ccw(point: Point) {
let b = this.vector();
let c = point.minus(this.points0); let length = b.abs() * c.abs();
if (b.cross(c) > length * EPS) {
return 1;
}
if (b.cross(c) < -length * EPS) {
return -1;
}
if (b.dot(c) < 0) {
return 2;
}
if (b.norm() < c.norm()) {
return -2;
}
return 0;
}
/**
* 2本の直線が平行かを判定します
* @param line
*/
paralell(line: LineModel) {
return this.vector().cross(line.vector()).sign() === 0;
}
/**
* 2本の直線が等しいかを判定します
* @param line
*/
same(line: LineModel) {
return (
this.vector().cross(this.points0.minus(line.points0)).sign() === 0 );
}
/**
* 直線と線分、もしくは直線と座標が交点を持つかを判定します
* @param object
*/
intersect(object: LineSegment | Point) {
if (object instanceof LineSegment) {
const seg = object as LineSegment;
return (
this.vector().cross(seg.points0.minus(this.points0)).sign() * this.vector().cross(seg.points1.minus(this.points0)) <= 0
);
}
if (object instanceof Point) {
return this.vector().cross(object.minus(this.points0)).sign() === 0; }
return undefined;
}
/**
* 2本の直線の交点を求めます
* @param line
*/
crossPoint(line: LineModel) {
let a = this.vector().cross(line.vector());
let b = this.vector().cross(this.points1.minus(line.points0)); if (Math.abs(a) < EPS && Math.abs(b) < EPS) {
}
if (Math.abs(a) < EPS) {
return null;
}
return line.points0.plus(line.vector().mult(b / a)); }
}
線分
code: geometry.ts
/**
* 線分オブジェクト
*/
export class LineSegment extends Path {
constructor(pos1: Point, pos2: Point) {
}
/**
* ベクトル座標
*/
vector(): Point {
return this.points1.minus(this.points0); }
/**
* 線分の長さ
*/
size(): number {
return this.vector().abs();
}
/**
* 単位ベクトル座標
*/
unitVector() {
return this.vector().div(this.size());
}
/**
* 直線に対する点の位置
*/
ccw(point: Point) {
let b = this.vector();
let c = point.minus(this.points0); let length = b.abs() * c.abs();
if (b.cross(c) > length * EPS) {
return 1;
}
if (b.cross(c) < -length * EPS) {
return -1;
}
if (b.dot(c) < 0) {
return 2;
}
if (b.norm() < c.norm()) {
return -2;
}
return 0;
}
intersect(object: Point | LineSegment) {
if (object instanceof Point) {
return this.ccw(object) === 0;
}
if (object instanceof LineSegment) {
return (
this.ccw(object.points0) * this.ccw(object.points1) <= 0 && object.ccw(this.points0) * object.ccw(this.points1) <= 0 );
}
return undefined;
}
crossPoint(line: LineSegment) {
if (!this.intersect(line)) {
return null;
}
let a = this.vector().cross(line.vector());
let b = this.vector().cross(this.points1.minus(line.points0)); if (Math.abs(a) < EPS && Math.abs(b) < EPS) {
}
if (Math.abs(a) < EPS) {
return null;
}
return line.points0.plus(line.vector().mult(b / a)); }
midPoint() {
return this.points0.midPoint(this.points1); }
}
ベクトル
code: geometry.ts
/**
* ベクトル(方向付き線分)クラス
*/
class Vector extends LineSegment {
origin: Point;
constructor(origin: Point, vec: Point) {
super(origin, origin.plus(vec));
this.origin = origin;
}
}