多角形・パス
多角形
code: geometry.ts
/**
* 多角形クラス
*/
class Polygonal {
points: Array<Point>;
static initClass() {
this.prototype.points = [];
}
constructor(points: Array<Point>) {
this.points = points;
}
}
Polygonal.initClass();
パス
code: geometry.ts
/**
* パスクラス
* 座標のリストを順に辿るパス
*/
export class Path {
/**
* 座標のリスト
*/
points: Array<Point>;
constructor(points: Array<Point>) {
this.points = points;
}
/**
* パスの基準となる座標、最初の座標を返します
*/
base() {
}
/**
* 座標のリストを反転させたパスを返します
*/
reverse() {
return new Path(this.points.reverse());
}
/**
* 2つのパスが等しいかを判定します
* @param path
*/
eq(path: Path) {
for (let index = 0; index < this.points.length; index++) {
let point = this.pointsindex; if (!point.eq(path.pointsindex)) { return false;
}
}
return true;
}
/**
* 基準点の位置を固定したままパスを拡大縮小します
* @param scale
*/
scale(scale: number) {
if (scale == null) {
scale = 1;
}
for (
let i = 1, end = this.points.length, asc = 1 <= end;
asc ? i < end : i > end;
asc ? i++ : i--
) {
points.push(
this.pointsi.minus(this.base()).mult(scale).plus(this.base()) );
}
return new Path(points);
}
/**
* 基準点の座標を固定したままパスを回転させます
* @param angle 回転角(ラジアン)
*/
rotate(angle: number) {
if (angle == null) {
angle = 0;
}
for (
let i = 1, end = this.points.length, asc = 1 <= end;
asc ? i < end : i > end;
asc ? i++ : i--
) {
points.push(
this.pointsi.minus(this.base()).rotate(angle).plus(this.base()) );
}
return new Path(points);
}
trancelation(position: Point) {
if (position == null) {
position = Pt(0, 0);
}
let points = [];
for (let point of Array.from(this.points)) {
points.push(point.plus(position));
}
return new Path(points);
}
/**
* 指定した直線を軸に線対象な
* 直線を指定しないとパスの1番目と2番目を軸に線対象なパスを返します
* @param line
*/
lineSymmetryBy(line?: LineModel) {
if (line == null) {
line = new LineModel(this.points0, this.points1); }
let points = [];
for (let point of Array.from(this.points)) {
points.push(point.lineSymmetryBy(line));
}
return new Path(points);
}
/**
* パスの1番目と2番目を軸に線対象なパスを返します
*/
lineSymmetry() {
return this.lineSymmetryBy();
}
/**
* 2つのパスが方向付きで合同かを判定します
* @param path 判定するパス
* @param symmetry 反転を許容
* @param rotate 回転を許容
*/
directedCongruent(path: Path, symmetry: boolean, rotate: boolean) {
if (symmetry == null) {
symmetry = true;
}
if (rotate == null) {
rotate = true;
}
path = path.trancelation(this.base().minus(path.base()));
if (rotate) {
let vec1 = this.points1.minus(this.base()); let vec2 = path.points1.minus(path.base()); let angle = Math.acos(vec1.dot(vec2) / (vec1.abs() * vec2.abs()));
path = path.rotate(angle);
}
if (symmetry) {
return this.eq(path) || this.eq(path.lineSymmetry());
} else {
return this.eq(path);
}
}
/**
* 2つのパスが方向付きで相似かを判定します
* @param path 判定するパス
* @param symmetry 反転を許容
* @param rotate 回転を許容
*/
directedSimilar(path: Path, symmetry: boolean, rotate: boolean) {
if (symmetry == null) {
symmetry = true;
}
if (rotate == null) {
rotate = true;
}
let scale =
this.points1.minus(this.points0).abs() / path.points1.minus(path.points0).abs(); return this.directedCongruent(path.scale(scale), symmetry, rotate);
}
/**
* 2つのパスが合同かを判定します
* @param path 判定するパス
* @param symmetry 反転を許容
* @param rotate 回転を許容
*/
congruent(path: Path, symmetry: boolean, rotate: boolean, direct: boolean) {
if (symmetry == null) {
symmetry = true;
}
if (rotate == null) {
rotate = true;
}
if (direct == null) {
direct = false;
}
if (direct) {
return this.directedCongruent(path, symmetry, rotate);
} else {
return (
this.directedCongruent(path, symmetry, rotate) ||
this.directedCongruent(path.reverse(), symmetry, rotate)
);
}
}
/**
* 2つのパスが相似かを判定します
* @param path 判定するパス
* @param symmetry 反転を許容
* @param rotate 回転を許容
* @param direct 方向を考慮
*/
similar(path: Path, symmetry: boolean, rotate: boolean, direct: boolean) {
if (symmetry == null) {
symmetry = true;
}
if (rotate == null) {
rotate = true;
}
if (direct == null) {
direct = false;
}
if (direct) {
return this.directedSimilar(path, symmetry, rotate);
} else {
return (
this.directedSimilar(path, symmetry, rotate) ||
this.directedSimilar(path.reverse(), symmetry, rotate)
);
}
}
/**
* 2つのパスが反転を許容せず回転合同かを判定します
* @param path
* @param direct 方向を考慮
*/
onesidedCongruent(path: Path, direct: boolean) {
if (direct == null) {
direct = false;
}
return this.congruent(path, false, true, direct);
}
/**
* 2つのパスが反転を許容せず回転合同かを判定します
* @param path
* @param direct 方向を考慮
*/
onesidedSimilar(path: Path, direct: boolean) {
if (direct == null) {
direct = false;
}
return this.similar(path, false, true, direct);
}
/**
* 2つのパスが回転・反転を許容せず合同かを判定します
* @param path
* @param direct 方向を考慮
*/
fixedCongruent(path: Path, direct: boolean) {
if (direct == null) {
direct = false;
}
return this.congruent(path, false, false, direct);
}
/**
* 2つのパスが回転・反転を許容せず相似かを判定します
* @param path
* @param direct 方向を考慮
*/
fixedSimilar(path: Path, direct: boolean) {
if (direct == null) {
direct = false;
}
return this.similar(path, false, false, direct);
}
}