organizing math module - move common geometry to euclidean module

This commit is contained in:
Val Erastov (xibyte) 2020-07-19 15:50:33 -07:00
parent 210eed5101
commit 2ffec12989
21 changed files with 246 additions and 251 deletions

View file

@ -1,154 +1,3 @@
import Vector from 'math/vector';
import BBox from '../../web/app/math/bbox'
import * as vec from 'math/vec';
import {perp2d} from 'math/vec';
import {eqTol} from "../../web/app/brep/geom/tolerance";
import {IDENTITY_BASIS3} from "math/basis";
import {distance} from "math/distance";
import {TOLERANCE} from "math/equality";
export function circleFromPoints(p1, p2, p3) {
var center = new Vector();
var offset = p2.x*p2.x + p2.y*p2.y;
var bc = ( p1.x*p1.x + p1.y*p1.y - offset )/2.0;
var cd = (offset - p3.x*p3.x - p3.y*p3.y)/2.0;
var det = (p1.x - p2.x) * (p2.y - p3.y) - (p2.x - p3.x)* (p1.y - p2.y);
if (Math.abs(det) < TOLERANCE) { return null; }
var idet = 1/det;
center.x = (bc * (p2.y - p3.y) - cd * (p1.y - p2.y)) * idet;
center.y = (cd * (p1.x - p2.x) - bc * (p2.x - p3.x)) * idet;
return center;
}
export function norm2(vec) {
var sq = 0;
for (var i = 0; i < vec.length; i++) {
sq += vec[i] * vec[i];
}
return Math.sqrt(sq);
}
export function rotate(px, py, angle) {
return rotateInPlace(px, py, angle, new Vector());
}
export function rotateInPlace(px, py, angle, out) {
out.x = px * Math.cos(angle) - py * Math.sin(angle);
out.y = px * Math.sin(angle) + py * Math.cos(angle);
return out;
}
export function polygonOffsetXY(polygon, scaleX, scaleY) {
const origBBox = new BBox();
const scaledBBox = new BBox();
const result = [];
for (let point of polygon) {
const scaledPoint = new Vector(point.x * scaleX, point.y * scaleY);
result.push(scaledPoint);
origBBox.checkPoint(point);
scaledBBox.checkPoint(scaledPoint);
}
const alignVector = scaledBBox.center()._minus(origBBox.center());
for (let point of result) {
point._minus(alignVector);
}
return result;
}
export function polygonOffset( polygon, scale ) {
return polygonOffsetXY( polygon, scale, scale );
}
export function polygonOffsetByDelta( polygon, delta ) {
const origBBox = new BBox();
for (let point of polygon) {
origBBox.checkPoint(point);
}
const width = origBBox.width();
const height = origBBox.height();
return polygonOffsetXY(polygon, (width + delta) / width, (height + delta) / height);
}
export function isPointInsidePolygon( inPt, inPolygon ) {
var EPSILON = TOLERANCE;
var polyLen = inPolygon.length;
// inPt on polygon contour => immediate success or
// toggling of inside/outside at every single! intersection point of an edge
// with the horizontal line through inPt, left of inPt
// not counting lowerY endpoints of edges and whole edges on that line
var inside = false;
for( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
var edgeLowPt = inPolygon[ p ];
var edgeHighPt = inPolygon[ q ];
var edgeDx = edgeHighPt.x - edgeLowPt.x;
var edgeDy = edgeHighPt.y - edgeLowPt.y;
if ( Math.abs(edgeDy) > EPSILON ) { // not parallel
if ( edgeDy < 0 ) {
edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
}
if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
if ( inPt.y == edgeLowPt.y ) {
if ( inPt.x == edgeLowPt.x ) return true; // inPt is on contour ?
// continue; // no intersection or edgeLowPt => doesn't count !!!
} else {
var perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
if ( perpEdge == 0 ) return true; // inPt is on contour ?
if ( perpEdge < 0 ) continue;
inside = ! inside; // true intersection left of inPt
}
} else { // parallel or colinear
if ( inPt.y != edgeLowPt.y ) continue; // parallel
// egde lies on the same horizontal line as inPt
if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
// continue;
}
}
return inside;
}
// http://en.wikipedia.org/wiki/Shoelace_formula
export function area(contour) {
var n = contour.length;
var a = 0.0;
for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
}
return a * 0.5;
}
export function isCCW(path2D) {
return area(path2D) >= 0;
}
export function findLowestLeftPoint(poly) {
let heroIdx = 0;
for (let i = 1; i< poly.length; ++i) {
const point = poly[i];
let hero = poly[heroIdx];
if (point.y < hero.y) {
heroIdx = i;
} else if (hero.y == point.y) {
if (point.x < hero.x) {
heroIdx = i;
}
}
}
return heroIdx;
}
export const _360 = 2 * Math.PI;
export const _90 = 0.5 * Math.PI;
export const _270 = 1.5 * Math.PI;
@ -161,71 +10,10 @@ export function makeAngle0_360(angle) {
return angle;
}
export function perpendicularVector(v) {
v = vec.normalize(v);
return IDENTITY_BASIS3.map(axis => vec.cross(axis, v)).sort((a, b) => vec.lengthSq(b) - vec.lengthSq(a))[0];
}
export function radiusOfCurvature(d1, d2) {
let r1lsq = vec.lengthSq(d1);
let r1l = Math.sqrt(r1lsq);
return r1lsq * r1l / vec.length(vec.cross(d1, d2));
}
export function pointToLineSignedDistance(ax, ay, bx, by, px, py) {
let nx = - (by - ay);
let ny = bx - ax;
const d = distance(ax, ay, bx, by);
nx /= d;
ny /= d;
let vx = px - ax;
let vy = py - ay;
const proj = vx * ny + vy * (-nx);
//Check if vector b lays on the vector ab
if (proj > d) {
return Number.NaN;
}
if (proj < 0) {
return Number.NaN;
}
return vx * nx + vy * ny;
}
export function lineLineIntersection2d(p1, p2, v1, v2) {
// const n1 = perp2d(v1);
const n2 = perp2d(v2);
const cos = vec.dot(n2, v1);
if (eqTol(cos, 0)) {
return null;
}
const u1 = vec.dot(n2, vec.sub(p2, p1)) / cos;
// const u2 = vec.dot(n1, vec.sub(p1, p2)) / vec.dot(n1, v2);
return [p1[0] + v1[0] * u1, p1[1] + v1[1] * u1];
}
export function lineLineIntersection(p1, p2, v1, v2) {
let zAx = v1.cross(v2);
const n1 = zAx.cross(v1)._normalize();
const n2 = zAx.cross(v2)._normalize();
return {
u1: n2.dot(p2.minus(p1)) / n2.dot(v1),
u2: n1.dot(p1.minus(p2)) / n1.dot(v2),
}
}
export const DEG_RAD = Math.PI / 180.0;
export const sq = (a) => a * a;
export function clamp(num, min, max) {
return Math.min(max, Math.max(num, min))
}

View file

@ -0,0 +1,204 @@
import BBox from "../../web/app/math/bbox";
import {TOLERANCE} from "math/equality";
import * as vec from "math/vec";
import {perp2d} from "math/vec";
import {eqTol} from "../../web/app/brep/geom/tolerance";
import {distance} from "math/distance";
import {IDENTITY_BASIS3} from "math/basis";
import Vector from "math/vector";
export function circleFromPoints(p1, p2, p3) {
var center = new Vector();
var offset = p2.x * p2.x + p2.y * p2.y;
var bc = (p1.x * p1.x + p1.y * p1.y - offset) / 2.0;
var cd = (offset - p3.x * p3.x - p3.y * p3.y) / 2.0;
var det = (p1.x - p2.x) * (p2.y - p3.y) - (p2.x - p3.x) * (p1.y - p2.y);
if (Math.abs(det) < TOLERANCE) {
return null;
}
var idet = 1 / det;
center.x = (bc * (p2.y - p3.y) - cd * (p1.y - p2.y)) * idet;
center.y = (cd * (p1.x - p2.x) - bc * (p2.x - p3.x)) * idet;
return center;
}
export function rotate(px, py, angle) {
return rotateInPlace(px, py, angle, new Vector());
}
export function rotateInPlace(px, py, angle, out) {
out.x = px * Math.cos(angle) - py * Math.sin(angle);
out.y = px * Math.sin(angle) + py * Math.cos(angle);
return out;
}
export function polygonOffsetXY(polygon, scaleX, scaleY) {
const origBBox = new BBox();
const scaledBBox = new BBox();
const result = [];
for (let point of polygon) {
const scaledPoint = new Vector(point.x * scaleX, point.y * scaleY);
result.push(scaledPoint);
origBBox.checkPoint(point);
scaledBBox.checkPoint(scaledPoint);
}
const alignVector = scaledBBox.center()._minus(origBBox.center());
for (let point of result) {
point._minus(alignVector);
}
return result;
}
export function polygonOffset(polygon, scale) {
return polygonOffsetXY(polygon, scale, scale);
}
export function polygonOffsetByDelta(polygon, delta) {
const origBBox = new BBox();
for (let point of polygon) {
origBBox.checkPoint(point);
}
const width = origBBox.width();
const height = origBBox.height();
return polygonOffsetXY(polygon, (width + delta) / width, (height + delta) / height);
}
export function isPointInsidePolygon(inPt, inPolygon) {
var EPSILON = TOLERANCE;
var polyLen = inPolygon.length;
// inPt on polygon contour => immediate success or
// toggling of inside/outside at every single! intersection point of an edge
// with the horizontal line through inPt, left of inPt
// not counting lowerY endpoints of edges and whole edges on that line
var inside = false;
for (var p = polyLen - 1, q = 0; q < polyLen; p = q++) {
var edgeLowPt = inPolygon[p];
var edgeHighPt = inPolygon[q];
var edgeDx = edgeHighPt.x - edgeLowPt.x;
var edgeDy = edgeHighPt.y - edgeLowPt.y;
if (Math.abs(edgeDy) > EPSILON) { // not parallel
if (edgeDy < 0) {
edgeLowPt = inPolygon[q];
edgeDx = -edgeDx;
edgeHighPt = inPolygon[p];
edgeDy = -edgeDy;
}
if ((inPt.y < edgeLowPt.y) || (inPt.y > edgeHighPt.y)) continue;
if (inPt.y == edgeLowPt.y) {
if (inPt.x == edgeLowPt.x) return true; // inPt is on contour ?
// continue; // no intersection or edgeLowPt => doesn't count !!!
} else {
var perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
if (perpEdge == 0) return true; // inPt is on contour ?
if (perpEdge < 0) continue;
inside = !inside; // true intersection left of inPt
}
} else { // parallel or colinear
if (inPt.y != edgeLowPt.y) continue; // parallel
// egde lies on the same horizontal line as inPt
if (((edgeHighPt.x <= inPt.x) && (inPt.x <= edgeLowPt.x)) ||
((edgeLowPt.x <= inPt.x) && (inPt.x <= edgeHighPt.x))) return true; // inPt: Point on contour !
// continue;
}
}
return inside;
}
export function area(contour) {
var n = contour.length;
var a = 0.0;
for (var p = n - 1, q = 0; q < n; p = q++) {
a += contour[p].x * contour[q].y - contour[q].x * contour[p].y;
}
return a * 0.5;
}
export function isCCW(path2D) {
return area(path2D) >= 0;
}
export function findLowestLeftPoint(poly) {
let heroIdx = 0;
for (let i = 1; i < poly.length; ++i) {
const point = poly[i];
let hero = poly[heroIdx];
if (point.y < hero.y) {
heroIdx = i;
} else if (hero.y == point.y) {
if (point.x < hero.x) {
heroIdx = i;
}
}
}
return heroIdx;
}
export function perpendicularVector(v) {
v = vec.normalize(v);
return IDENTITY_BASIS3.map(axis => vec.cross(axis, v)).sort((a, b) => vec.lengthSq(b) - vec.lengthSq(a))[0];
}
export function radiusOfCurvature(d1, d2) {
let r1lsq = vec.lengthSq(d1);
let r1l = Math.sqrt(r1lsq);
return r1lsq * r1l / vec.length(vec.cross(d1, d2));
}
export function pointToLineSignedDistance(ax, ay, bx, by, px, py) {
let nx = -(by - ay);
let ny = bx - ax;
const d = distance(ax, ay, bx, by);
nx /= d;
ny /= d;
let vx = px - ax;
let vy = py - ay;
const proj = vx * ny + vy * (-nx);
//Check if vector b lays on the vector ab
if (proj > d) {
return Number.NaN;
}
if (proj < 0) {
return Number.NaN;
}
return vx * nx + vy * ny;
}
export function lineLineIntersection2d(p1, p2, v1, v2) {
// const n1 = perp2d(v1);
const n2 = perp2d(v2);
const cos = vec.dot(n2, v1);
if (eqTol(cos, 0)) {
return null;
}
const u1 = vec.dot(n2, vec.sub(p2, p1)) / cos;
// const u2 = vec.dot(n1, vec.sub(p1, p2)) / vec.dot(n1, v2);
return [p1[0] + v1[0] * u1, p1[1] + v1[1] * u1];
}
export function lineLineIntersection(p1, p2, v1, v2) {
let zAx = v1.cross(v2);
const n1 = zAx.cross(v1)._normalize();
const n2 = zAx.cross(v2)._normalize();
return {
u1: n2.dot(p2.minus(p1)) / n2.dot(v1),
u2: n1.dot(p1.minus(p2)) / n1.dot(v2),
}
}

View file

@ -173,3 +173,13 @@ export default class Vector {
scale: (scalar: number) => Vector = Vector.prototype.multiply;
_scale: (scalar: number) => Vector = Vector.prototype._multiply;
}
const freeze = Object.freeze;
export const ORIGIN = freeze(new Vector(0, 0, 0));
export const AXIS = freeze({
X: freeze(new Vector(1, 0, 0)),
Y: freeze(new Vector(0, 1, 0)),
Z: freeze(new Vector(0, 0, 1))
});

View file

@ -1,6 +1,6 @@
import * as vec from 'math/vec';
import {perpendicularVector} from '../../math/commons';
import {Face3, Geometry, Vector3} from 'three';
import {perpendicularVector} from "../../math/euclidean";
export function createMeshLineGeometry(points, width) {
const vThree = arr => new Vector3().fromArray(arr);

View file

@ -4,17 +4,17 @@ import {Edge} from './topo/edge';
import BrepCurve from './geom/curves/brepCurve';
import {Plane} from './geom/impl/plane';
import * as cad_utils from '../cad/cad-utils';
import * as math from '../../../modules/math/commons';
import {createBoundingSurface} from './brep-builder';
import NurbsSurface from './geom/surfaces/nurbsSurface';
import {BrepSurface} from './geom/surfaces/brepSurface';
import {Matrix3} from 'math/matrix';
import {BasisForPlane} from "math/basis";
import {isCCW as isCCWtest} from "math/euclidean";
function isCCW(points, normal) {
const tr2d = new Matrix3().setBasis(BasisForPlane(normal)).invert();
const points2d = points.map(p => tr2d.apply(p));
return math.isCCW(points2d);
return isCCWtest(points2d);
}
function checkCCW(points, normal) {

View file

@ -1,5 +1,5 @@
import * as vec from 'math/vec';
import {perpendicularVector} from '../../../../../modules/math/commons';
import {perpendicularVector} from "../../../../../modules/math/euclidean";
export function frenetFrame(D1, D2) {
let T = vec.normalize(D1);

View file

@ -1,8 +1,8 @@
import {Face} from '../topo/face';
import {Vertex} from '../topo/vertex';
import Vector from 'math/vector';
import {isCCW} from '../../../../modules/math/commons';
import PIP from '../../cad/tess/pip';
import {isCCW} from "../../../../modules/math/euclidean";
export function evolveFace(originFace, loops) {
let out = [];

View file

@ -1,9 +1,8 @@
import {TopoObject} from './topo-object'
import * as math from 'math/commons'
import {Face} from "./face";
import {BrepSurface} from "../geom/surfaces/brepSurface";
import {HalfEdge} from "./edge";
import {findLowestLeftPoint} from "math/euclidean";
export class Loop extends TopoObject {
@ -58,7 +57,7 @@ export class Loop extends TopoObject {
private static isPolygonCCWOnSurface(polygon: any[], surface: BrepSurface) {
const tr = surface.simpleSurface.get2DTransformation();
const polygon2d = polygon.map(p => tr.apply(p));
const lowestLeftIdx = math.findLowestLeftPoint(polygon2d);
const lowestLeftIdx = findLowestLeftPoint(polygon2d);
const n = polygon.length;
const nextIdx = ((lowestLeftIdx + 1) % n);
const prevIdx = ((n + lowestLeftIdx - 1) % n);

View file

@ -1,5 +1,5 @@
import libtess from 'libtess'
import {area} from "../../../../modules/math/commons";
import {area} from "../../../../modules/math/euclidean";
export default function pickPointInside2dPolygon(polygon) {
function vertexCallback(data, tr) {

View file

@ -1,13 +1,14 @@
import Vector from "math/vector";
import {FaceTouchAlignConstraint} from "../constraints/faceTouchAlign";
import {AssemblyDOF, ModificationResponse} from "./assemblyDOF";
import {clamp, DEG_RAD, lineLineIntersection} from "math/commons";
import {clamp, DEG_RAD} from "math/commons";
import {ConflictDOF} from "./conflictDOF";
import {EdgeAlignConstraint} from "../constraints/edgeAlign";
import {PPEEDOF} from "./PPEEDOF";
import {EEEEDOF} from "./EEEEDOF";
import {Matrix3} from "math/matrix";
import {areEqual} from "math/equality";
import {lineLineIntersection} from "math/euclidean";
const ANGULAR_ALLOWANCE = 10 * DEG_RAD;

View file

@ -1,9 +1,12 @@
import Vector from 'math/vector';
import BBox from '../math/bbox'
import * as math from '../../../modules/math/commons'
import {MeshSceneSolid} from './scene/wrappers/meshSceneObject'
import {Matrix3} from 'math/matrix';
import {equal} from 'math/equality';
import {area, isCCW, isPointInsidePolygon} from "math/euclidean";
export {area, isCCW, isPointInsidePolygon};
export const FACE_COLOR = 0xB0C4DE;
@ -220,8 +223,6 @@ export function fixCCW(path, normal) {
return path;
}
export const isPointInsidePolygon = math.isPointInsidePolygon;
export function someBasis2(normal) {
var x = normal.cross(normal.randomNonParallelVector());
var y = normal.cross(x).unit();
@ -259,9 +260,6 @@ export function normalOfCCWSeqTHREE(ccwSequence) {
return b.sub(a).cross(c.sub(a)).normalize();
}
export const area = math.area;
export const isCCW = math.isCCW;
export function calculateExtrudedLid(sourcePolygon, normal, direction, expansionFactor) {
var lid = [];
var length = sourcePolygon.length;

View file

@ -1,12 +1,12 @@
import Vector from 'math/vector';
import * as cad_utils from '../../cad-utils'
import * as math from '../../../../../modules/math/commons'
import {HashTable} from '../../../utils/hashmap'
import {Mesh} from '../mesh'
import revolve from './revolve'
import {Triangulate} from '../../tess/triangulation'
import {distanceAB3} from "../../../../../modules/math/distance";
import {areEqual, equal, strictEqual} from "../../../../../modules/math/equality";
import {isPointInsidePolygon} from "../../../../../modules/math/euclidean";
export function sortPolygons(polygons) {
function Loop(polygon) {
@ -16,7 +16,7 @@ export function sortPolygons(polygons) {
}
function contains(polygon, other) {
for (let point of other._2D) {
if (!math.isPointInsidePolygon(point, polygon._2D)) {
if (!isPointInsidePolygon(point, polygon._2D)) {
return false;
}
}

View file

@ -4,7 +4,7 @@ import brepTess from '../../tess/brep-tess';
import tessellateSurface from '../../../brep/geom/surfaces/surfaceTess';
import {setAttribute} from '../../../../../modules/scene/objectData';
import * as vec from 'math/vec';
import {perpendicularVector} from '../../../../../modules/math/commons';
import {perpendicularVector} from "math/euclidean";
const SMOOTH_RENDERING = true;

View file

@ -1,4 +1,3 @@
import {circleFromPoints, radiusOfCurvature} from '../../../../modules/math/commons';
import * as vec from 'math/vec';
import {iteratePath} from '../cad-utils';
import NurbsCurve from '../../brep/geom/curves/nurbsCurve';
@ -6,6 +5,7 @@ import {veqXYZ} from '../../brep/geom/tolerance';
import curveTess, {curveTessParams} from '../../brep/geom/impl/curve/curve-tess';
import {distanceAB} from "math/distance";
import {areEqual, TOLERANCE} from "math/equality";
import {circleFromPoints, radiusOfCurvature} from "../../../../modules/math/euclidean";
export function getSketchBoundaries(sceneFace) {
const boundary = {lines: [], arcs: [], circles: [], nurbses: []};

View file

@ -3,11 +3,12 @@ import BrepCurve from '../../brep/geom/curves/brepCurve';
import NurbsCurve from '../../brep/geom/curves/nurbsCurve';
import {Point} from '../../brep/geom/point'
import {LUT} from '../../math/bezier-cubic'
import {isCCW, makeAngle0_360} from '../../../../modules/math/commons'
import {makeAngle0_360} from '../../../../modules/math/commons'
import {normalizeCurveEnds} from '../../brep/geom/impl/nurbs-ext';
import Vector, {AXIS, ORIGIN} from '../../../../modules/math/vector';
import CSys from "../../../../modules/math/csys";
import {distanceAB} from "../../../../modules/math/distance";
import {isCCW} from "../../../../modules/math/euclidean";
const RESOLUTION = 20;

View file

@ -1,5 +1,5 @@
import pip from "./pip";
import {isCCW} from "../../../../modules/math/commons";
import {isCCW} from "../../../../modules/math/euclidean";
export default function(loops) {
const loops = loops.map(loop => new NestedLoop(loop));

View file

@ -4,8 +4,7 @@ import {LUT} from '../../math/bezier-cubic'
import {ConvexHull2D} from '../../math/convex-hull'
import * as draw_utils from '../shapes/draw-utils'
import * as math from '../../../../modules/math/commons';
import {EndPoint} from "./point";
import {isPointInsidePolygon, polygonOffset} from "../../../../modules/math/euclidean";
export class BezierCurve extends SketchObject {
@ -53,8 +52,8 @@ export class BezierCurve extends SketchObject {
normalDistance(aim, scale) {
this.hull = ConvexHull2D([this.a, this.b, this.cp1, this.cp2]);
this.hull = math.polygonOffset(this.hull, 1 + (0.3 / scale));
if (math.isPointInsidePolygon(aim, this.hull)) {
this.hull = polygonOffset(this.hull, 1 + (0.3 / scale));
if (isPointInsidePolygon(aim, this.hull)) {
this.lut = LUT(this.a, this.b, this.cp1, this.cp2, scale);
return this.closestNormalDistance(aim, this.lut)
}

View file

@ -1,9 +1,6 @@
import {
DEG_RAD,
lineLineIntersection2d,
makeAngle0_360,
pointToLineSignedDistance
} from '../../../../modules/math/commons'
makeAngle0_360} from '../../../../modules/math/commons'
import * as vec from 'math/vec'
import Vector from 'math/vector';
import {Styles} from "../styles";
@ -12,6 +9,7 @@ import {isInstanceOf} from "../actions/matchUtils";
import {Arc} from "./arc";
import {SketchObject} from "./sketch-object";
import {distance, distanceAB} from "../../../../modules/math/distance";
import {lineLineIntersection2d, pointToLineSignedDistance} from "../../../../modules/math/euclidean";
const ARROW_W_PX = 15;
const ARROW_H_PX = 4;

View file

@ -1,5 +1,6 @@
import {_270, _90, makeAngle0_360, pointToLineSignedDistance} from "../../../../modules/math/commons";
import {_270, _90, makeAngle0_360} from "../../../../modules/math/commons";
import {_negate} from "math/vec";
import {pointToLineSignedDistance} from "../../../../modules/math/euclidean";
export class TextHelper {

View file

@ -1,10 +1,8 @@
import {Tool} from './tool'
import {EndPoint} from '../shapes/point'
import {BezierCurve} from '../shapes/bezier-curve'
import {Constraints} from '../parametric'
import Vector from 'math/vector';
import * as math from '../../../../modules/math/commons'
import {AlgNumConstraint, ConstraintDefinitions} from "../constr/ANConstraints";
import {rotate} from "math/euclidean";
export class BezierCurveTool extends Tool {
@ -61,7 +59,7 @@ export class BezierCurveTool extends Tool {
this.curve.b.setFromPoint(p);
const axis = this._v.set(this.curve.b.x - this.curve.a.x, this.curve.b.y - this.curve.a.y)._multiply(0.7);
//controlSegment = {x: -controlSegment.y, y: controlSegment.x};
const controlSegment = math.rotate(- axis.y, axis.x, - Math.PI * 0.25);
const controlSegment = rotate(- axis.y, axis.x, - Math.PI * 0.25);
if (this.otherCurveEndPoint != null) {
const ctrlLength = axis.length();
this.curve.cp1.x = this.curve.a.x + this.snappedControl.x * ctrlLength;

View file

@ -1,10 +1,8 @@
import {LoopPickTool} from './loop-pick'
import {Constraints} from '../parametric'
import * as math from '../../../../modules/math/commons';
import Vector from 'math/vector';
import {swap} from '../../utils/utils'
import {EndPoint} from '../shapes/point'
import {Arc} from '../shapes/arc'
import {isCCW} from "../../../../modules/math/euclidean";
export class OffsetTool extends LoopPickTool {
@ -36,7 +34,7 @@ export class OffsetTool extends LoopPickTool {
return (i + low) % length;
}
const mainInverse = !this.twoConnectedArcs() && math.isCCW([loopPoints[pos(0)], loopPoints[pos(1)], loopPoints[pos(length - 1)]]);
const mainInverse = !this.twoConnectedArcs() && isCCW([loopPoints[pos(0)], loopPoints[pos(1)], loopPoints[pos(length - 1)]]);
const pm = this.viewer.parametricManager;
const offsetConstant = createOffsetConstant(pm, delta);