/* * iGeom by LInE * Geometric Object: Circumference * Model to Circumference * www.matematica.br/igeom * ./app/components/line-component/models/circumference-model.js * @version 2020/11/02: Implemented Line instersection */ import { ELEMENTS_CLASS } from "../../../core/enums/elements-class-enum"; import { GeometricObject } from "../../../core/models/objects/geometric-object"; import { IntersectionModel } from "../../intersection-component/models/intersection-model"; export class CircumferenceModel extends GeometricObject { constructor(center, radius, id) { super(id); this.center = center; this.radius = radius; this._coordinates = []; this._coordinates[0] = this.center.posX; this._coordinates[1] = this.center.posY; this._coordinates[2] = this.radius.posX; this._coordinates[3] = this.radius.posY; this.color = -16776961; super.setClass(ELEMENTS_CLASS.CIRCUMFERENCE); this.definitions.push(this.center); this.definitions.push(this.radius); } getCenter() { return this.center; } getPoint() { return this.radius; } getRadius () { return this.radius; // the point } getRadiusValue () { // return ||this.center - this.radius|| //_ Deixar mais intuitiva... //_ this._coordinates[0] = this.center.posX; //_ this._coordinates[1] = this.center.posY; //_ this._coordinates[2] = this.radius.posX; //_ this._coordinates[3] = this.radius.posY; //_ const legA = this._coordinates[2] - this._coordinates[0]; //_ const legB = this._coordinates[3] - this._coordinates[1]; //_ const radius = Math.sqrt(Math.pow(legA, 2) + Math.pow(legB, 2)); // Desnecessario! //_ return radius; var Cx, Cy, Ax, Ay; Cx = this._coordinates[0] = this.center.posX; Cy = this._coordinates[1] = this.center.posY; Ax = this._coordinates[2] = this.radius.posX; Ay = this._coordinates[3] = this.radius.posY; //D console.log("circumference-model.js: circ(" + Cx + "," + Cy + "), (" + Ax + "," + Ay + ")"); const dx = Ax - Cx; const dy = Ay - Cy; const radius = Math.sqrt(dx * dx + dy * dy); return radius; } getStraight () { const dx = this.radius.posX - this.center.posX; const dy = this.radius.posY - this.center.posY; const c = Math.sqrt(dy * dy + dx * dx); return [dx, dy, c]; } getDirection () { const aX = this.center.posX; const aY = this.center.posY; const bX = this.radius.posX; const bY = this.radius.posY; const a = bX - aX; const b = bY - aY; return [a, b]; } getIntersection (geometricObject) { switch (geometricObject.elementClass) { case ELEMENTS_CLASS.LINE: // StraightLine return geometricObject.getIntersectionWithCircumference(this); // Delegate to StraightLine case ELEMENTS_CLASS.LINE_SEGMENT: return this.getIntersectionByLine(geometricObject); //TODO melhor 'with' que 'by' case ELEMENTS_CLASS.CIRCUMFERENCE: return this.getIntersectionsByCircumference(geometricObject); //TODO melhor 'with' que 'by' default: break; } } distance (center) { const dx = center.posX - this.center.posX; const dy = center.posY - this.center.posY; const dist = Math.sqrt(dy * dy + dx * dx); return dist; } getIntersectionsByCircumference (circumference) { //TODO if (this.cente().igual(cd.C())) return null; // duas circ. com mesmo raio => devolva "null" (ambiguidade!) const r1 = this.getRadiusValue(); // raio circ. atual const r2 = circumference.getRadiusValue(); // raio circ. "cd" const d = this.distance(circumference); // distancia entre os raios das circ. if (r1 + r2 < d || Math.abs(r1 - r2) > d) return null; const A = this.center; // pega o centro da circunferencia atual const B = circumference.center; // pega o centro da circunferencia "cd" const x = B.posX - A.posX; const y = B.posY - A.posY; let cos = x / Math.sqrt(x * x + y * y); //(B.posX-A.posX)/Math.sqrt(x*x + y*y); // cos a = /(|z||w|) let sen = Math.sqrt(1 - cos * cos); if (A.posY > B.posY) sen = -sen; let u1 = B.posX - A.posX; let v1 = B.posY - A.posY; let u = u1 * cos + v1 * sen; let v = -u1 * sen + v1 * cos; const rA = this.getRadiusValue(); const rB = circumference.getRadiusValue(); u = (u * u - rB * rB + rA * rA) / (2 * u); v = Math.sqrt(rA * rA - u * u); v1 = v; let v2 = -v; let x1 = u * cos - v1 * sen; let y1 = u * sen + v1 * cos; let x2 = u * cos - v2 * sen; let y2 = u * sen + v2 * cos; x1 = A.posX + x1; y1 = A.posY + y1; x2 = A.posX + x2; y2 = A.posY + y2; return [ new IntersectionModel(x1, y1, undefined, this, circumference, true, 0), new IntersectionModel(x2, y2, undefined, this, circumference, true, 1) ]; } /// Get Intersection Poin By Circumference and Line Segment /// @param {LineSegmentModel } lineSegment getIntersectionByLine (lineSegment) { const pointA = lineSegment.pointA, pointB = lineSegment.pointB; // sl = segment(A,B) const center = this.center, radius = this.getRadiusValue(); // c0 = circunference(C,A) = circ("center,radius") const dx = pointB.posX - pointA.posX; const dy = pointB.posY - pointA.posY; const cx = center.posX - pointA.posX; const cy = center.posY - pointA.posY; const a = dx * dx + dy * dy; const b = dx * cx + dy * cy; const c = cx * cx + cy * cy - radius * radius; const D = b / a; const q = c / a; const delta = D * D - q; const PA = new IntersectionModel(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 0); const PB = new IntersectionModel(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 1); if (delta < 0) { return [PA, PB]; } const deltaSqrt = Math.sqrt(delta); const root1 = -D + deltaSqrt; const root2 = -D - deltaSqrt; const x1 = pointA.posX - dx * root1 const y1 = pointA.posY - dy * root1; if (delta == 0) { PA.bind(x1, y1, undefined, lineSegment, this, true, 0); return [PA, PB]; } const x2 = pointA.posX - dx * root2; const y2 = pointA.posY - dy * root2; PA.bind(x1, y1, undefined, lineSegment, this, true, 0); PB.bind(x2, y2, undefined, lineSegment, this, true, 1); if (this.visible) { if (!this.insideSegment(PA.posX, PA.posY)) PA.bind(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 0) if (!this.insideSegment(PB.posX, PB.posY)) PB.bind(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 1) } return [PA, PB]; } // Verify intersection using "level set" insideSegment (intersecX, intersecY) { const valuesR = this.getDirection(); const dirX = valuesR[0]; const dirY = valuesR[1]; const cInterA = dirX * intersecX + dirY * intersecY; // comparaca cv do ponto A > cv da intersec => vazio const cRA = dirX * this.center.posX + dirY * this.center.posY; if (cInterA < cRA) { return false; } // comparaca cv do ponto B < cv da intersec => vazio const cRB = dirX * this.radius.posX + dirY * this.radius.posY; if (cInterA > cRB) { this.posX = Number.MAX_SAFE_INTEGER; this.posY = Number.MAX_SAFE_INTEGER; return false; } return true; } static do (map, vecIdObj, list) { const id = map.get("id"); const centerId = map.get("param")[0]; const radiusId = map.get("param")[1]; // const center = list.find(x => x.id === centerId); // const radius = list.find(x => x.id === radiusId); const index_center = GeometricObject.findOD(vecIdObj, centerId); // get the index of vecIdObj[ii].id == centerId const index_radius = GeometricObject.findOD(vecIdObj, radiusId); // get the index of vecIdObj[ii].id == radiusId const center = list[index_center]; // center Point const radius = list[index_radius]; // Point defining circumference radius const label = map.get("label")[0]; const circumference = new CircumferenceModel(center, radius, id); circumference.setLabel(label); return circumference; } } // export class CircumferenceModel extends GeometricObject