123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050 |
- import Constant from "../Constant";
- export default class MathUtil {
- constructor() {}
- getFixed(num, decimal) {
- if (!decimal) {
- decimal = 5;
- }
- // return Math.floor(num * 10000) / 10000;
- return parseFloat(num.toFixed(decimal));
- }
- // 求两个点的距离
- getDistance(p1, p2) {
- const x1 = p1.x;
- const y1 = p1.y;
- const x2 = p2.x;
- const y2 = p2.y;
- const num = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
- return this.getFixed(num);
- }
- createLine1(point1, point2) {
- if (point1.x == point2.x && point1.y == point2.y) {
- return null;
- } else if (this.getFixed(Math.abs(point1.x - point2.x)) == 0) {
- return { x: point1.x };
- } else if (this.getFixed(Math.abs(point1.y - point2.y)) == 0) {
- return { y: point1.y };
- }
- const parametera = (point1.y - point2.y) / (point1.x - point2.x);
- const parameterb =
- (point1.x * point2.y - point2.x * point1.y) / (point1.x - point2.x);
- if (this.getFixed(parametera) == 0) {
- return { y: this.getFixed(parameterb) };
- }
- const parameter = {
- a: this.getFixed(parametera),
- b: this.getFixed(parameterb),
- };
- return parameter;
- }
- createLine2(point, angle) {
- if (angle == Math.PI / 2 || angle == 1.5 * Math.PI) {
- return { x: point.x };
- }
- let a = Math.tan(angle);
- let b = point.y - a * point.x;
- if (a != 0) {
- return { a: a, b: b };
- } else {
- return { y: point.y };
- }
- }
- // 与lineA平行并且point在线上
- createLine3(lineA, point) {
- const parameter = {};
- if (typeof lineA.a === "undefined") {
- if (typeof lineA.x !== "undefined") {
- parameter.x = point.x;
- } else if (typeof lineA.y !== "undefined") {
- parameter.y = point.y;
- }
- } else {
- parameter.a = lineA.a;
- parameter.b = point.y - point.x * lineA.a;
- }
- return parameter;
- }
- create2AngleLine(point, angle, driftAngle) {
- let line1 = this.createLine2(point, angle - driftAngle / 2);
- let line2 = this.createLine2(point, angle + driftAngle / 2);
- return { line1: line1, line2: line2 };
- }
- distanceForPoints(point1, point2) {
- return Math.sqrt(
- Math.pow(point1.x - point2.x, 2) + Math.pow(point1.y - point2.y, 2)
- );
- }
- //与line平行且两条线直接的距离是distance的两条线
- getParallelLineForDistance(line, distance) {
- let line1 = {};
- let line2 = {};
- if (!line.hasOwnProperty("a")) {
- if (line.hasOwnProperty("x")) {
- let x = line.x;
- line1.x = x + distance;
- line2.x = x - distance;
- } else if (line.hasOwnProperty("y")) {
- let y = line.y;
- line1.y = y + distance;
- line2.y = y - distance;
- }
- } else {
- line1.a = line.a;
- line1.b = line.b;
- line2.a = line.a;
- line2.b = line.b;
- let angle = Math.atan(line.a);
- let db = Math.abs(distance / Math.cos(angle));
- let b = line.b;
- line1.b = b + db;
- line2.b = b - db;
- }
- return { line1: line1, line2: line2 };
- }
- //获取扇形的两个端点
- getEndpoint(point, angle, sectorAngle) {
- const distance = 15;
- //line1是减,line2是加
- let lines1 = this.create2AngleLine(point, angle, sectorAngle);
- let line = this.createLine2(point, angle);
- line = this.getLineForPoint(line, point);
- let lines2 = this.getParallelLineForDistance(line, distance);
- let point1 = this.getIntersectionPoint(lines1.line1, lines2.line1);
- let point2 = this.getIntersectionPoint(lines1.line1, lines2.line2);
- let point3 = this.getIntersectionPoint(lines1.line2, lines2.line1);
- let point4 = this.getIntersectionPoint(lines1.line2, lines2.line2);
- let angle1 = this.Angle(point, point1, { x: point.x + 1, y: point.y });
- let angle2 = this.Angle(point, point2, { x: point.x + 1, y: point.y });
- let angle3 = this.Angle(point, point3, { x: point.x + 1, y: point.y });
- let angle4 = this.Angle(point, point4, { x: point.x + 1, y: point.y });
- if (angle > Math.PI) {
- angle = 2 * Math.PI - angle;
- }
- if (
- Math.abs((angle1 + angle3) / 2 - angle) <
- Math.abs((angle2 + angle4) / 2 - angle)
- ) {
- return { p1: point1, p2: point3 };
- } else {
- return { p1: point2, p2: point4 };
- }
- }
- // true表示逆时针,false表示顺时针
- isClockwise(vertices) {
- let area = 0;
- for (let i = 0; i < vertices.length; i++) {
- const j = (i + 1) % vertices.length;
- area += vertices[i].x * vertices[j].y;
- area -= vertices[j].x * vertices[i].y;
- }
- const sub = area / 2;
- if (sub > 0) {
- // 逆时针
- return true;
- } else {
- // 顺时针
- return false;
- }
- }
- reverse(points) {
- const _points = [];
- for (let i = points.length - 1; i > -1; --i) {
- _points.push(points[i]);
- }
- return _points;
- }
- //两条线的交点
- getIntersectionPoint(parameter1, parameter2) {
- if (this.isParallel(parameter1, parameter2)) {
- return null;
- }
- if (
- typeof parameter1.a == "undefined" &&
- typeof parameter2.a != "undefined"
- ) {
- if (parameter1.x) {
- return {
- x: parameter1.x,
- y: parameter2.a * parameter1.x + parameter2.b,
- };
- } else if (parameter1.y) {
- return {
- x: (parameter1.y - parameter2.b) / parameter2.a,
- y: parameter1.y,
- };
- }
- } else if (
- typeof parameter2.a == "undefined" &&
- typeof parameter1.a != "undefined"
- ) {
- if (parameter2.x) {
- return {
- x: parameter2.x,
- y: parameter1.a * parameter2.x + parameter1.b,
- };
- } else if (parameter2.y) {
- return {
- x: (parameter2.y - parameter1.b) / parameter1.a,
- y: parameter2.y,
- };
- }
- } else if (
- typeof parameter2.a == "undefined" &&
- typeof parameter1.a == "undefined"
- ) {
- if (parameter1.hasOwnProperty("x") && parameter2.hasOwnProperty("y")) {
- return { x: parameter1.x, y: parameter2.y };
- } else if (
- parameter1.hasOwnProperty("y") &&
- parameter2.hasOwnProperty("x")
- ) {
- return { x: parameter2.x, y: parameter1.y };
- } else {
- return null;
- }
- }
- if (parameter1.a == parameter2.a) {
- return null;
- }
- let joinpointx =
- (parameter2.b - parameter1.b) / (parameter1.a - parameter2.a);
- let joinpointy =
- (parameter1.a * parameter2.b - parameter2.a * parameter1.b) /
- (parameter1.a - parameter2.a);
- let point = { x: joinpointx, y: joinpointy };
- return point;
- }
- // 直线的交点
- getIntersectionPoint2(a, b, c, d) {
- /** 1 解线性方程组, 求线段交点. **/
- // 如果分母为0 则平行或共线, 不相交
- const denominator = (b.y - a.y) * (d.x - c.x) - (a.x - b.x) * (c.y - d.y);
- if (denominator == 0) {
- return null;
- }
- // 线段所在直线的交点坐标 (x , y)
- const x =
- ((b.x - a.x) * (d.x - c.x) * (c.y - a.y) +
- (b.y - a.y) * (d.x - c.x) * a.x -
- (d.y - c.y) * (b.x - a.x) * c.x) /
- denominator;
- const y =
- -(
- (b.y - a.y) * (d.y - c.y) * (c.x - a.x) +
- (b.x - a.x) * (d.y - c.y) * a.y -
- (d.x - c.x) * (b.y - a.y) * c.y
- ) / denominator;
- return { x: x, y: y };
- }
- //两条线段交点
- getIntersectionPoint3(a, b, c, d) {
- const join = this.getIntersectionPoint2(a, b, c, d);
- if (join) {
- const x = join.x;
- const y = join.y; // 交点在线段1上 且交点也在线段2上
- /** 2 判断交点是否在两条线段上 **/
- if (
- (x - a.x) * (x - b.x) <= 0.001 &&
- (y - a.y) * (y - b.y) <= 0.001 &&
- (x - c.x) * (x - d.x) <= 0.001 &&
- (y - c.y) * (y - d.y) <= 0.001
- ) {
- // 返回交点p
- return {
- x: x,
- y: y,
- };
- }
- return null;
- }
- return null;
- }
- // 线段和直线是否相交
- getIntersectionPoint4(point1, point2, line) {
- const line1 = this.createLine1(point1, point2);
- const join = this.getIntersectionPoint(line1, line);
- if (join == null) {
- return null;
- }
- if (this.PointInSegment(join, point1, point2)) {
- return join; // 相交
- } else {
- return null;
- }
- }
- //返回true表示平行
- isParallel(line1, line2) {
- if (typeof line1.a == "undefined" && typeof line2.a == "undefined") {
- if (line1.hasOwnProperty("x") && line2.hasOwnProperty("x")) {
- return true;
- } else if (line1.hasOwnProperty("y") && line2.hasOwnProperty("y")) {
- return true;
- } else {
- return false;
- }
- } else if (typeof line1.a == "undefined" || typeof line2.a == "undefined") {
- return false;
- } else if (this.getFixed(line1.a) == this.getFixed(line2.a)) {
- return true;
- } else {
- return false;
- }
- }
- //两条相交的线段的夹角,永远小于180度
- Angle(o, s, e) {
- let cosfi = 0,
- fi = 0,
- norm = 0;
- let dsx = s.x - o.x;
- let dsy = s.y - o.y;
- let dex = e.x - o.x;
- let dey = e.y - o.y;
- cosfi = dsx * dex + dsy * dey;
- norm = (dsx * dsx + dsy * dsy) * (dex * dex + dey * dey);
- cosfi /= Math.sqrt(norm);
- if (cosfi >= 1.0) return 0;
- //if (cosfi <= -1.0) return Math.PI;
- if (cosfi <= -1.0) return Math.PI;
- fi = Math.acos(cosfi);
- if ((180 * fi) / Math.PI < 180) {
- //return 180 * fi / Math.PI;
- return (fi * 180) / Math.PI;
- } else {
- //return 360 - 180 * fi / Math.PI;
- return ((2 * Math.PI - fi) * 180) / Math.PI;
- }
- }
- //经过point且与line垂直的线
- getLineForPoint(line, point) {
- let parameter = {};
- if (line.a == 0 || typeof line.a == "undefined") {
- if (line.hasOwnProperty("x")) {
- parameter.y = point.y;
- } else if (line.hasOwnProperty("y")) {
- parameter.x = point.x;
- }
- } else {
- parameter.a = -1 / line.a;
- parameter.b = point.y - point.x * parameter.a;
- }
- return parameter;
- }
- // 经过point且与line垂直的直线,该直线与line的交点
- getJoinLinePoint(point, line) {
- const verticalLine = this.getVerticalLine(line, point);
- const join = this.getIntersectionPoint(line, verticalLine);
- return join;
- }
- // 点到直线的距离
- getDisForPoinLine(point, line) {
- const join = this.getJoinLinePoint(point, line);
- return this.getDistance(point, join);
- }
- // 垂直线
- getVerticalLine(line, point) {
- if (typeof line.a === "undefined") {
- if (line.hasOwnProperty("x")) {
- return { y: point.y };
- } else if (line.hasOwnProperty("y")) {
- return { x: point.x };
- } else {
- return null;
- }
- } else if (line.a == 0) {
- return { x: point.x };
- } else {
- const tl = {};
- tl.a = -1 / line.a;
- const result = this.createLine3(tl, point);
- return result;
- }
- }
- //point在直线上,只是不确定是否在线段上
- //方法:point到startPoint和endPoint的距离之和与startPoint和endPoint之间的距离对比
- isContainForSegment(point, startPoint, endPoint, minDis) {
- if (!minDis) {
- minDis = Constant.minLen;
- }
- let dis1 =
- this.getDistance(startPoint, point) + this.getDistance(endPoint, point);
- let dis2 = this.getDistance(startPoint, endPoint);
- if (Math.abs(dis1 - dis2) < minDis) {
- return true;
- } else {
- return false;
- }
- }
- /*
- //minDis
- isPointInPoly(point, points, minDis) {
- if (!minDis) {
- minDis = Constant.minRealDis
- }
- const x = point.x
- const y = point.y
- let inside = false
- // 是否在顶点附近
- for (let i = 0; i < points.length; ++i) {
- let distance = this.getDistance(point, points[i])
- if (distance < minDis) {
- return true
- }
- }
- // 是否在边沿
- for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
- let pt1 = points[i]
- let pt2 = points[j]
- const flag = this.isContainForSegment(point, pt1, pt2, minDis)
- if (flag) {
- return true
- }
- }
- for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
- let pt1 = points[i]
- let pt2 = points[j]
- const xi = pt1.x
- const yi = pt1.y
- const xj = pt2.x
- const yj = pt2.y
- const intersect = yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi
- if (intersect) inside = !inside
- }
- return inside
- }
- */
- isPointInPoly(point, points) {
- const x = point.x;
- const y = point.y;
- let inside = false;
- for (let i = 0, j = points.length - 1; i < points.length; j = i++) {
- let pt1 = points[i];
- let pt2 = points[j];
- const xi = pt1.x;
- const yi = pt1.y;
- const xj = pt2.x;
- const yj = pt2.y;
- const intersect =
- yi > y != yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi;
- if (intersect) inside = !inside;
- }
- return inside;
- }
- // 点到线段的距离
- // 在minDistance范围内,会吸附到point1/point2上
- // 返回值:type是1表示吸附在point1,是2表示吸附在point2,是0表示在线段point1-point2上;
- getDisForPoinSegment(point, point1, point2, minDistance) {
- const line = this.createLine1(point1, point2);
- const join = this.getJoinLinePoint(point, line);
- const dis = this.getDistance(point1, point2);
- const dis1 = this.getDistance(join, point1);
- const dis2 = this.getDistance(join, point2);
- if (
- this.getDistance(join, point1) > dis ||
- this.getDistance(join, point2) > dis
- ) {
- // 在线段外
- if (dis1 < dis2 && dis1 < minDistance) {
- return { type: 1, join: point1 };
- } else if (dis2 < dis1 && dis2 < minDistance) {
- return { type: 2, join: point2 };
- } else {
- return null;
- }
- } else {
- if (dis1 < minDistance) {
- return { type: 1, join: point1 };
- } else if (dis2 < minDistance) {
- return { type: 2, join: point2 };
- } else if (this.getDistance(point, join) < minDistance) {
- return { type: 0, join: join };
- }
- }
- }
- PointInSegment(Q, pi, pj, minDis) {
- if (
- this.getDistance(Q, pi) < Constant.minAdsorbPix ||
- this.getDistance(Q, pj) < Constant.minAdsorbPix
- ) {
- return true;
- }
- if (!minDis) {
- minDis = 0.1;
- }
- minDis = minDis / 2;
- const offset1 = (Q.x - pi.x) * (pj.y - pi.y) - (pj.x - pi.x) * (Q.y - pi.y);
- const offset2 = Math.min(pi.x, pj.x) - Q.x;
- const offset3 = Q.x - Math.max(pi.x, pj.x);
- const offset4 = Math.min(pi.y, pj.y) - Q.y;
- const offset5 = Q.y - Math.max(pi.y, pj.y);
- if (
- Math.abs(offset1) < minDis &&
- (offset2 <= 0 || Math.abs(offset2) < minDis) &&
- (offset3 <= 0 || Math.abs(offset3) < minDis) &&
- (offset4 <= 0 || Math.abs(offset4) < minDis) &&
- (offset5 <= 0 || Math.abs(offset5) < minDis)
- ) {
- return true;
- } else {
- return false;
- }
- }
- //点p是否在线段AB上
- isPointOnSegment(p, A, B) {
- // 计算向量 AP 和 BP
- const AP = {
- x: p.x - A.x,
- y: p.y - A.y,
- };
- const BP = {
- x: p.x - B.x,
- y: p.y - B.y,
- };
- // 计算向量 AB 的长度和方向
- const AB = {
- x: B.x - A.x,
- y: B.y - A.y,
- };
- const AB_length = this.getDistance(A, B);
- const AB_direction = {
- x: AB.x / AB_length,
- y: AB.y / AB_length,
- };
- // 检查 AP 和 BP 的方向是否与 AB 相同,并检查它们的长度是否小于等于 AB 的长度
- const dot_product_AP = AP.x * AB_direction.x + AP.y * AB_direction.y;
- const dot_product_BP = BP.x * AB_direction.x + BP.y * AB_direction.y;
- //return dot_product_AP >= 0 && dot_product_BP <= 0 && Math.abs(AP.x * BP.y - AP.y * BP.x) <= AB_length * Number.EPSILON;
- return (
- dot_product_AP >= 0 &&
- dot_product_BP <= 0 &&
- Math.abs(AP.x * BP.y - AP.y * BP.x) <= 0.01
- );
- }
- clonePoint(p1, p2) {
- p1.x = p2.x;
- p1.y = p2.y;
- }
- equalPoint(p1, p2) {
- if (p1.x == p2.x && p1.y == p2.y) {
- return true;
- } else {
- return false;
- }
- }
- crossTwoLines(point1, point2, point3, point4, dis) {
- if (typeof dis == "undefined") {
- dis = Constant.minAdsorbPix;
- }
- const join = this.getIntersectionPoint2(point1, point2, point3, point4);
- if (join != null) {
- if (
- this.getDistance(point1, join) > dis &&
- this.getDistance(point2, join) > dis &&
- this.getDistance(point3, join) > dis &&
- this.getDistance(point4, join) > dis
- ) {
- if (
- this.getDistance(point1, join) < this.getDistance(point1, point2) &&
- this.getDistance(point2, join) < this.getDistance(point1, point2) &&
- this.getDistance(point3, join) < this.getDistance(point3, point4) &&
- this.getDistance(point4, join) < this.getDistance(point3, point4)
- ) {
- return true;
- } else {
- return false;
- }
- }
- } else {
- if (
- this.PointInSegment(point1, point3, point4) ||
- this.PointInSegment(point2, point3, point4)
- ) {
- return true;
- }
- }
- return false;
- }
- getDisPointsLine(line, point, distance1, distance2) {
- const newpoint1 = {};
- const newpoint2 = {};
- const result = {};
- if (line.hasOwnProperty("x")) {
- newpoint1.x = line.x;
- newpoint1.y = point.y - distance1;
- newpoint2.x = line.x;
- newpoint2.y = point.y + distance2;
- } else if (line.hasOwnProperty("y")) {
- newpoint1.y = line.y;
- newpoint1.x = point.x - distance1;
- newpoint2.y = line.y;
- newpoint2.x = point.x + distance2;
- } else {
- const a = Math.atan(line.a);
- const t_line = { a: -1 / line.a };
- const line_ab2 = this.createLine3(t_line, point);
- const join = this.getIntersectionPoint(line, line_ab2);
- newpoint1.x = join.x - distance1 * Math.cos(a);
- newpoint1.y = join.y - distance1 * Math.sin(a);
- newpoint2.x = join.x + distance2 * Math.cos(a);
- newpoint2.y = join.y + distance2 * Math.sin(a);
- }
- result.newpoint1 = newpoint1;
- result.newpoint2 = newpoint2;
- return result;
- }
- getBoundingBox(points) {
- let minX = points[0].x;
- let maxX = points[0].x;
- let minY = points[0].y;
- let maxY = points[0].y;
- for (let i = 1; i < points.length; ++i) {
- const point = points[i];
- if (minX > point.x) {
- minX = point.x;
- }
- if (minY > point.y) {
- minY = point.y;
- }
- if (maxX < point.x) {
- maxX = point.x;
- }
- if (maxY < point.y) {
- maxY = point.y;
- }
- }
- const box = {};
- box.minX = minX;
- box.minY = minY;
- box.maxX = maxX;
- box.maxY = maxY;
- return box;
- }
- getBoundingBox2(points) {
- let minX = null;
- let maxX = null;
- let minY = null;
- let maxY = null;
- for (let key in points) {
- const point = points[key];
- if (minX == null || minX > point.x) {
- minX = point.x;
- }
- if (minY == null || minY > point.y) {
- minY = point.y;
- }
- if (maxX == null || maxX < point.x) {
- maxX = point.x;
- }
- if (maxY == null || maxY < point.y) {
- maxY = point.y;
- }
- }
- const box = {};
- box.minX = minX;
- box.minY = minY;
- box.maxX = maxX;
- box.maxY = maxY;
- return box;
- }
- ComputePolygonArea(points) {
- const point_num = points.length;
- if (point_num < 3) {
- return 0;
- }
- let s = points[0].y * (points[point_num - 1].x - points[1].x);
- for (let i = 1; i < point_num; ++i)
- s += points[i].y * (points[i - 1].x - points[(i + 1) % point_num].x);
- return Math.abs(s / 2.0);
- }
- // 获取多边形重心
- getPolygonCore(points) {
- function Area(p0, p1, p2) {
- let area = 0.0;
- area =
- p0.x * p1.y +
- p1.x * p2.y +
- p2.x * p0.y -
- p1.x * p0.y -
- p2.x * p1.y -
- p0.x * p2.y;
- return area / 2;
- }
- let sum_x = 0;
- let sum_y = 0;
- let sum_area = 0;
- let p1 = points[1];
- for (let i = 2; i < points.length; i++) {
- const p2 = points[i];
- const area = Area(points[0], p1, p2);
- sum_area += area;
- sum_x += (points[0].x + p1.x + p2.x) * area;
- sum_y += (points[0].y + p1.y + p2.y) * area;
- p1 = p2;
- }
- const xx = sum_x / sum_area / 3;
- const yy = sum_y / sum_area / 3;
- return {
- x: xx,
- y: yy,
- };
- }
- // points1是否在points2里
- isPolyInPoly(points1, points2, minDis) {
- for (let i = 0; i < points1.length; ++i) {
- let flag = false;
- for (let j = 0; j < points2.length; ++j) {
- if (this.equalPoint(points1[i], points2[j])) {
- flag = true;
- break;
- }
- }
- if (!flag) {
- if (!this.isPointInPoly(points1[i], points2, minDis)) {
- return false;
- }
- } else {
- const nextIndex = i == points1.length - 1 ? 0 : i + 1;
- const mid = {
- x: (points1[i].x + points1[nextIndex].x) / 2,
- y: (points1[i].y + points1[nextIndex].y) / 2,
- };
- if (!this.isPointInPoly(mid, points2, minDis)) {
- return false;
- }
- }
- }
- return true;
- }
- dotPoints(pt1, pt2, point1, point2) {
- let vt1 = {};
- let vt2 = {};
- vt1.start = {};
- vt1.end = {};
- vt1.start.x = 0;
- vt1.start.y = 0;
- vt1.end.x = pt2.x - pt1.x;
- vt1.end.y = pt2.y - pt1.y;
- vt2.start = {};
- vt2.end = {};
- vt2.start.x = 0;
- vt2.start.y = 0;
- vt2.end.x = point2.x - point1.x;
- vt2.end.y = point2.y - point1.y;
- let result = vt1.end.x * vt2.end.x + vt1.end.y * vt2.end.y;
- return result;
- }
- //start是起点,target是朝着目标移动,distance是移动的距离
- translate(start, target, point, distance) {
- let dx = target.x - start.x;
- let dy = target.y - start.y;
- let dis = Math.sqrt(Math.pow(dx, 2) + Math.pow(dy, 2));
- let result = {
- x: point.x + (dx * distance) / dis,
- y: point.y + (dy * distance) / dis,
- };
- return result;
- }
- //射线与线段相交
- // intersection(rayStart, rayEnd, segmentStart, segmentEnd) {
- // // 计算射线和线段的方向向量
- // const rayDirection = {
- // x:rayEnd.x - rayStart.x,
- // y:rayEnd.y - rayStart.y,
- // };
- // const segmentDirection = {
- // x:segmentEnd.x - segmentStart.x,
- // y:segmentEnd.y - segmentStart.y,
- // };
- // // 计算射线和线段的起点之间的向量
- // const startPointVector = {
- // x:rayStart.x - segmentStart.x,
- // y:rayStart.y - segmentStart.y,
- // };
- // // 计算射线和线段的叉积
- // const crossProduct = rayDirection.x * segmentDirection.y - rayDirection.y * segmentDirection.x;
- // // 如果叉积为0,则表示射线和线段平行
- // if (crossProduct === 0) {
- // return null;
- // }
- // // 计算线段起点到射线的交点的向量
- // const t = (startPointVector.x * segmentDirection.y - startPointVector.y * segmentDirection.x) / crossProduct;
- // // 如果t的值小于0,则交点在射线的起点之后
- // if (t < 0) {
- // return null;
- // }
- // // 计算交点的坐标
- // const intersectionX = rayStart.x + t * rayDirection.x;
- // const intersectionY = rayStart.y + t * rayDirection.y;
- // // 如果交点在线段的范围内,则返回交点坐标
- // if ((intersectionX >= Math.min(segmentStart.x, segmentEnd.x)) &&
- // (intersectionX <= Math.max(segmentStart.x, segmentEnd.x)) &&
- // (intersectionY >= Math.min(segmentStart.y, segmentEnd.y)) &&
- // (intersectionY <= Math.max(segmentStart.y, segmentEnd.y))) {
- // //return [intersectionX, intersectionY];
- // return {
- // x:intersectionX,
- // y:intersectionY,
- // };
- // }
- // // 否则返回null
- // return null;
- // }
- // raySegmentIntersection(rayOrigin, rayDirection, segmentStart, segmentEnd) {
- // // 计算射线和线段的交点
- // const x1 = rayOrigin.x
- // const y1 = rayOrigin.y
- // const x2 = segmentStart.x
- // const y2 = segmentStart.y
- // const dx1 = rayDirection.x
- // const dy1 = rayDirection.y
- // const dx2 = segmentEnd.x - x2
- // const dy2 = segmentEnd.y - y2
- // const crossProduct = dx1 * dy2 - dx2 * dy1
- // if (Math.abs(crossProduct) < 1e-8) {
- // // 射线和线段平行或共线
- // return null
- // }
- // const t1 = (dx2 * (y1 - y2) - dy2 * (x1 - x2)) / crossProduct
- // const t2 = (dx1 * (y1 - y2) - dy1 * (x1 - x2)) / crossProduct
- // if (t1 >= 0 && t2 >= 0 && t2 <= 1) {
- // // 有交点,计算交点坐标
- // const intersectionX = x1 + t1 * dx1
- // const intersectionY = y1 + t1 * dy1
- // return {
- // x: intersectionX,
- // y: intersectionY,
- // }
- // } else {
- // // 没有交点
- // return null
- // }
- // }
- raySegmentIntersection(rayOrigin, rayDirection, segmentStart, segmentEnd) {
- const end = {
- x: rayOrigin.x + rayDirection.x,
- y: rayOrigin.y - rayDirection.z,
- };
- const line = this.createLine1(rayOrigin, end);
- const join = this.getIntersectionPoint4(segmentStart, segmentEnd, line);
- if (join == null) {
- return null;
- } else {
- const dis = this.getDistance(end, join);
- const dis1 = this.getDistance(rayOrigin, join);
- const dis2 = this.getDistance(rayOrigin, end);
- if (dis - (dis1 + dis2) + 0.01 > 0) {
- return null;
- } else {
- return join;
- }
- }
- }
- RectangleVertex(startPoint, endPoint, width) {
- let line = this.createLine1(startPoint, endPoint);
- let lines = this.getParallelLineForDistance(line, width / 2);
- let leftEdgeStart, rightEdgeStart, rightEdgeEnd, leftEdgeEnd;
- let point = null;
- let points = [];
- //先计算start部分
- point = startPoint;
- points.push(endPoint);
- points.push(startPoint);
- let point1 = this.getJoinLinePoint(point, lines.line1);
- let point2 = this.getJoinLinePoint(point, lines.line2);
- points[2] = point1;
- if (this.isClockwise(points)) {
- rightEdgeStart = point1;
- leftEdgeStart = point2;
- } else {
- rightEdgeStart = point2;
- leftEdgeStart = point1;
- }
- //再计算end部分
- points = [];
- point = endPoint;
- points.push(startPoint);
- points.push(endPoint);
- point1 = this.getJoinLinePoint(point, lines.line1);
- point2 = this.getJoinLinePoint(point, lines.line2);
- points[2] = point1;
- if (this.isClockwise(points)) {
- rightEdgeEnd = point2;
- leftEdgeEnd = point1;
- } else {
- rightEdgeEnd = point1;
- leftEdgeEnd = point2;
- }
- return {
- leftEdgeStart: leftEdgeStart,
- rightEdgeStart: rightEdgeStart,
- rightEdgeEnd: rightEdgeEnd,
- leftEdgeEnd: leftEdgeEnd,
- };
- }
- //start到end的射线中取一点point,start-end和end-point的距离相同
- getPositionForExtendedLine(start, end) {
- const dx = end.x - start.x;
- const dy = end.y - start.y;
- const point = {
- x: end.x + dx,
- y: end.y + dy,
- };
- return point;
- }
- isOnRay(start, dir, position) {
- const v1 = { x: dir.x - start.x, y: dir.y - start.y };
- const v2 = { x: position.x - start.x, y: position.y - start.y };
- return v1.x * v2.y - v1.y * v2.x;
- }
- //向量是否同样的方向
- isSameDirForVector(point1, point2, p1, p2) {
- const v1 = {
- x: point2.x - point1.x,
- y: point2.y - point1.y,
- };
- const v2 = {
- x: p2.x - p1.x,
- y: p2.y - p1.y,
- };
- const value = this.dot(v1, v2);
- if (value > 0) {
- return true;
- }
- {
- return false;
- }
- }
- angleTo(v1, v2) {
- const denominator = Math.sqrt(this.lengthSq(v1) * this.lengthSq(v2));
- if (denominator === 0) return Math.PI / 2;
- const theta = this.dot(v1, v2) / denominator;
- //return Math.acos(this.clamp(theta, -1, 1));
- return (Math.acos(this.clamp(theta, -1, 1)) / Math.PI) * 180;
- }
- //点乘
- dot(v1, v2) {
- return v1.x * v2.x + v1.y * v2.y;
- }
- //叉乘
- cross(v1, v2) {
- return v1.x * v2.y - v1.y * v2.x;
- }
- clamp(value, min, max) {
- return Math.max(min, Math.min(max, value));
- }
- lengthSq(v) {
- return v.x * v.x + v.y * v.y;
- }
- }
- const mathUtil = new MathUtil();
- export { mathUtil };
|