cgas
Version:
Xtor Compute Geometry Algorithm Libary 计算几何算法库
414 lines (351 loc) • 11.2 kB
text/typescript
// import { Vec3 } from '../math/Vec3';
// var Edge = require('./edge');
// var martinez = require('martinez-polygon-clipping');
// var utils = require('./utils');
// var isArray = utils.isArray;
// var equals = utils.equals;
// var orientRings = utils.orientRings;
// /**
// * Offset builder
// *
// * @param {Array.<Object>=} vertices
// * @param {Number=} arcSegments
// * @constructor
// */
// export class Offset {
// vertices: null;
// edges: null;
// _closed: boolean;
// _distance: number;
// _arcSegments: any;
// constructor(vertices: Vec3[], arcSegments: any) {
// /**
// * @type {Array.<Object>}
// */
// this.vertices = null;
// /**
// * @type {Array.<Edge>}
// */
// this.edges = null;
// /**
// * @type {Boolean}
// */
// this._closed = false;
// /**
// * @type {Number}
// */
// this._distance = 0;
// if (vertices) {
// this.data(vertices);
// }
// /**
// * Segments in edge bounding arches
// * @type {Number}
// */
// this._arcSegments = arcSegments !== undefined ? arcSegments : 5;
// }
// /**
// * Change data set
// * @param {Array.<Array>} vertices
// * @return {Offset}
// */
// data(vertices: any[] | null) {
// this._edges = [];
// if (!isArray(vertices)) {
// throw new Error('Offset requires at least one coodinate to work with');
// }
// if (isArray(vertices) && typeof vertices[0] === 'number') {
// this.vertices = vertices;
// } else {
// this.vertices = orientRings(vertices);
// this._processContour(this.vertices, this._edges);
// }
// return this;
// }
// /**
// * Recursively process contour to create normals
// * @param {*} contour
// * @param {Array} edges
// */
// _processContour(contour: string | any[] | null, edges: any[]) {
// var i, len;
// if (isArray(contour[0]) && typeof contour[0][0] === 'number') {
// len = contour.length;
// if (equals(contour[0], contour[len - 1])) {
// len -= 1; // otherwise we get division by zero in normals
// }
// for (i = 0; i < len; i++) {
// edges.push(new Edge(contour[i], contour[(i + 1) % len]));
// }
// } else {
// for (i = 0, len = contour.length; i < len; i++) {
// edges.push([]);
// this._processContour(contour[i], edges[edges.length - 1]);
// }
// }
// }
// /**
// * @param {Number} arcSegments
// * @return {Offset}
// */
// arcSegments(arcSegments: any) {
// this._arcSegments = arcSegments;
// return this;
// }
// /**
// * Validates if the first and last points repeat
// * TODO: check CCW
// *
// * @param {Array.<Object>} vertices
// */
// validate(vertices: string | any[]) {
// var len = vertices.length;
// if (typeof vertices[0] === 'number') return [vertices];
// if (vertices[0][0] === vertices[len - 1][0] &&
// vertices[0][1] === vertices[len - 1][1]) {
// if (len > 1) {
// vertices = vertices.slice(0, len - 1);
// this._closed = true;
// }
// }
// return vertices;
// }
// /**
// * Creates arch between two edges
// *
// * @param {Array.<Object>} vertices
// * @param {Object} center
// * @param {Number} radius
// * @param {Object} startVertex
// * @param {Object} endVertex
// * @param {Number} segments
// * @param {Boolean} outwards
// */
// createArc(vertices: any[], center: number[], radius: number, startVertex: number[],
// endVertex: number[], segments: number, outwards: boolean) {
// var PI2 = Math.PI * 2,
// startAngle = Math.atan2(startVertex[1] - center[1], startVertex[0] - center[0]),
// endAngle = Math.atan2(endVertex[1] - center[1], endVertex[0] - center[0]);
// // odd number please
// if (segments % 2 === 0) {
// segments -= 1;
// }
// if (startAngle < 0) {
// startAngle += PI2;
// }
// if (endAngle < 0) {
// endAngle += PI2;
// }
// var angle = ((startAngle > endAngle) ?
// (startAngle - endAngle) :
// (startAngle + PI2 - endAngle)),
// segmentAngle = ((outwards) ? -angle : PI2 - angle) / segments;
// vertices.push(startVertex);
// for (var i = 1; i < segments; ++i) {
// angle = startAngle + segmentAngle * i;
// vertices.push([
// center[0] + Math.cos(angle) * radius,
// center[1] + Math.sin(angle) * radius
// ]);
// }
// vertices.push(endVertex);
// return vertices;
// }
// /**
// * @param {Number} dist
// * @param {String=} units
// * @return {Offset}
// */
// distance(dist: number, units: undefined) {
// this._distance = dist || 0;
// return this;
// }
// /**
// * @static
// * @param {Number} degrees
// * @param {String=} units
// * @return {Number}
// */
// degreesToUnits(degrees: number, units: any) {
// switch (units) {
// case 'miles':
// degrees = degrees / 69.047;
// break;
// case 'feet':
// degrees = degrees / 364568.0;
// break;
// case 'kilometers':
// degrees = degrees / 111.12;
// break;
// case 'meters':
// case 'metres':
// degrees = degrees / 111120.0;
// break;
// case 'degrees':
// case 'pixels':
// default:
// break;
// }
// return degrees;
// }
// /**
// * @param {Array.<Object>} vertices
// * @return {Array.<Object>}
// */
// ensureLastPoint(vertices: any[] | null) {
// if (!equals(vertices[0], vertices[vertices.length - 1])) {
// vertices.push([
// vertices[0][0],
// vertices[0][1]
// ]);
// }
// return vertices;
// }
// /**
// * Decides by the sign if it's a padding or a margin
// *
// * @param {Number} dist
// * @return {Array.<Object>}
// */
// offset(dist: any) {
// this.distance(dist);
// return this._distance === 0 ? this.vertices :
// (this._distance > 0 ? this.margin(this._distance) :
// this.padding(-this._distance));
// };
// /**
// * @param {Array.<Array.<Number>>} vertices
// * @param {Array.<Number>} pt1
// * @param {Array.<Number>} pt2
// * @param {Number} dist
// * @return {Array.<Array.<Number>>}
// */
// _offsetSegment(v1: any, v2: any, e1: { offset: (arg0: number, arg1: number) => any; _inNormal: number[]; inverseOffset: (arg0: number, arg1: number) => any; _outNormal: number[]; }, dist: number) {
// var vertices: never[] = [];
// var offsets = [
// e1.offset(e1._inNormal[0] * dist, e1._inNormal[1] * dist),
// e1.inverseOffset(e1._outNormal[0] * dist, e1._outNormal[1] * dist)
// ];
// for (var i = 0, len = 2; i < len; i++) {
// var thisEdge = offsets[i],
// prevEdge = offsets[(i + len - 1) % len];
// this.createArc(
// vertices,
// i === 0 ? v1 : v2, // edges[i].current, // p1 or p2
// dist,
// prevEdge.next,
// thisEdge.current,
// this._arcSegments,
// true
// );
// }
// return vertices;
// };
// /**
// * @param {Number} dist
// * @return {Array.<Number>}
// */
// margin(dist: number) {
// this.distance(dist);
// if (typeof this.vertices[0] === 'number') { // point
// return this.offsetPoint(this._distance);
// }
// if (dist === 0) return this.vertices;
// var union = this.offsetLines(this._distance);
// //return union;
// union = martinez.union(this.vertices, union);
// return orientRings(union);
// };
// /**
// * @param {Number} dist
// * @return {Array.<Number>}
// */
// padding(dist: number) {
// this.distance(dist);
// if (this._distance === 0) return this.ensureLastPoint(this.vertices);
// if (this.vertices.length === 2 && typeof this.vertices[0] === 'number') {
// return this.vertices;
// }
// var union = this.offsetLines(this._distance);
// var diff = martinez.diff(this.vertices, union);
// return orientRings(diff);
// };
// /**
// * Creates margin polygon
// * @param {Number} dist
// * @return {Array.<Object>}
// */
// offsetLine(dist: number) {
// if (dist === 0) return this.vertices;
// return orientRings(this.offsetLines(dist));
// };
// /**
// * Just offsets lines, no fill
// * @param {Number} dist
// * @return {Array.<Array.<Array.<Number>>>}
// */
// offsetLines(dist: number) {
// if (dist < 0) throw new Error('Cannot apply negative margin to the line');
// var union;
// this.distance(dist);
// if (isArray(this.vertices[0]) && typeof this.vertices[0][0] !== 'number') {
// for (var i = 0, len = this._edges.length; i < len; i++) {
// union = (i === 0) ?
// this.offsetContour(this.vertices[i], this._edges[i]) :
// martinez.union(union, this.offsetContour(this.vertices[i], this._edges[i]));
// }
// } else {
// union = (this.vertices.length === 1) ?
// this.offsetPoint() :
// this.offsetContour(this.vertices, this._edges);
// }
// return union;
// }
// /**
// * @param {Array.<Array.<Number>>|Array.<Array.<...>>} curve
// * @param {Array.<Edge>|Array.<Array.<...>>} edges
// * @return {Polygon}
// */
// offsetContour(curve: string | any[] | null, edges: string | any[]) {
// var union, i, len;
// if (isArray(curve[0]) && typeof curve[0][0] === 'number') {
// // we have 1 less edge than vertices
// for (i = 0, len = curve.length - 1; i < len; i++) {
// var segment = this.ensureLastPoint(
// this._offsetSegment(curve[i], curve[i + 1], edges[i], this._distance)
// );
// union = (i === 0) ?
// [this.ensureLastPoint(segment)] :
// martinez.union(union, this.ensureLastPoint(segment));
// }
// } else {
// for (i = 0, len = edges.length; i < len; i++) {
// union = (i === 0) ?
// this.offsetContour(curve[i], edges[i]) :
// martinez.union(union, this.offsetContour(curve[i], edges[i]));
// }
// }
// return union;
// };
// /**
// * @param {Number} distance
// * @return {Array.<Array.<Number>}
// */
// offsetPoint(distance: number | undefined) {
// this.distance(distance);
// var vertices = this._arcSegments * 2;
// var points = [];
// var center = this.vertices;
// var radius = this._distance;
// var angle = 0;
// if (vertices % 2 === 0) vertices++;
// for (var i = 0; i < vertices; i++) {
// angle += (2 * Math.PI / vertices); // counter-clockwise
// points.push([
// center[0] + (radius * Math.cos(angle)),
// center[1] + (radius * Math.sin(angle))
// ]);
// }
// return orientRings([this.ensureLastPoint(points)]);
// }
// }