circumference-model.js 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. /*
  2. * iGeom by LInE
  3. * Geometric Object: Circumference
  4. * Model to Circumference
  5. * www.matematica.br/igeom
  6. * ./app/components/line-component/models/circumference-model.js
  7. * @version 2020/11/02: Implemented Line instersection
  8. */
  9. import { ELEMENTS_CLASS } from "../../../core/enums/elements-class-enum";
  10. import { GeometricObject } from "../../../core/models/objects/geometric-object";
  11. import { IntersectionModel } from "../../intersection-component/models/intersection-model";
  12. export class CircumferenceModel extends GeometricObject {
  13. constructor(center, radius, id) {
  14. super(id);
  15. this.center = center;
  16. this.radius = radius;
  17. this._coordinates = [];
  18. this._coordinates[0] = this.center.posX;
  19. this._coordinates[1] = this.center.posY;
  20. this._coordinates[2] = this.radius.posX;
  21. this._coordinates[3] = this.radius.posY;
  22. this.color = -16776961;
  23. super.setClass(ELEMENTS_CLASS.CIRCUMFERENCE);
  24. this.definitions.push(this.center);
  25. this.definitions.push(this.radius);
  26. }
  27. getCenter() {
  28. return this.center;
  29. }
  30. getPoint() {
  31. return this.radius;
  32. }
  33. getRadius () {
  34. return this.radius; // the point
  35. }
  36. getRadiusValue () { // return ||this.center - this.radius||
  37. //_ Deixar mais intuitiva...
  38. //_ this._coordinates[0] = this.center.posX;
  39. //_ this._coordinates[1] = this.center.posY;
  40. //_ this._coordinates[2] = this.radius.posX;
  41. //_ this._coordinates[3] = this.radius.posY;
  42. //_ const legA = this._coordinates[2] - this._coordinates[0];
  43. //_ const legB = this._coordinates[3] - this._coordinates[1];
  44. //_ const radius = Math.sqrt(Math.pow(legA, 2) + Math.pow(legB, 2)); // Desnecessario!
  45. //_ return radius;
  46. var Cx, Cy, Ax, Ay;
  47. Cx = this._coordinates[0] = this.center.posX;
  48. Cy = this._coordinates[1] = this.center.posY;
  49. Ax = this._coordinates[2] = this.radius.posX;
  50. Ay = this._coordinates[3] = this.radius.posY;
  51. //D console.log("circumference-model.js: circ(" + Cx + "," + Cy + "), (" + Ax + "," + Ay + ")");
  52. const dx = Ax - Cx;
  53. const dy = Ay - Cy;
  54. const radius = Math.sqrt(dx * dx + dy * dy);
  55. return radius;
  56. }
  57. getStraight () {
  58. const dx = this.radius.posX - this.center.posX;
  59. const dy = this.radius.posY - this.center.posY;
  60. const c = Math.sqrt(dy * dy + dx * dx);
  61. return [dx, dy, c];
  62. }
  63. getDirection () {
  64. const aX = this.center.posX;
  65. const aY = this.center.posY;
  66. const bX = this.radius.posX;
  67. const bY = this.radius.posY;
  68. const a = bX - aX;
  69. const b = bY - aY;
  70. return [a, b];
  71. }
  72. getIntersection (geometricObject) {
  73. switch (geometricObject.elementClass) {
  74. case ELEMENTS_CLASS.LINE: // StraightLine
  75. return geometricObject.getIntersectionWithCircumference(this); // Delegate to StraightLine
  76. case ELEMENTS_CLASS.LINE_SEGMENT:
  77. return this.getIntersectionByLine(geometricObject); //TODO melhor 'with' que 'by'
  78. case ELEMENTS_CLASS.CIRCUMFERENCE:
  79. return this.getIntersectionsByCircumference(geometricObject); //TODO melhor 'with' que 'by'
  80. default:
  81. break;
  82. }
  83. }
  84. distance (center) {
  85. const dx = center.posX - this.center.posX;
  86. const dy = center.posY - this.center.posY;
  87. const dist = Math.sqrt(dy * dy + dx * dx);
  88. return dist;
  89. }
  90. getIntersectionsByCircumference (circumference) {
  91. //TODO if (this.cente().igual(cd.C())) return null; // duas circ. com mesmo raio => devolva "null" (ambiguidade!)
  92. const r1 = this.getRadiusValue(); // raio circ. atual
  93. const r2 = circumference.getRadiusValue(); // raio circ. "cd"
  94. const d = this.distance(circumference); // distancia entre os raios das circ.
  95. if (r1 + r2 < d || Math.abs(r1 - r2) > d) return null;
  96. const A = this.center; // pega o centro da circunferencia atual
  97. const B = circumference.center; // pega o centro da circunferencia "cd"
  98. const x = B.posX - A.posX;
  99. const y = B.posY - A.posY;
  100. let cos = x / Math.sqrt(x * x + y * y); //(B.posX-A.posX)/Math.sqrt(x*x + y*y); // cos a = <z,w>/(|z||w|)
  101. let sen = Math.sqrt(1 - cos * cos);
  102. if (A.posY > B.posY) sen = -sen;
  103. let u1 = B.posX - A.posX;
  104. let v1 = B.posY - A.posY;
  105. let u = u1 * cos + v1 * sen;
  106. let v = -u1 * sen + v1 * cos;
  107. const rA = this.getRadiusValue();
  108. const rB = circumference.getRadiusValue();
  109. u = (u * u - rB * rB + rA * rA) / (2 * u);
  110. v = Math.sqrt(rA * rA - u * u);
  111. v1 = v;
  112. let v2 = -v;
  113. let x1 = u * cos - v1 * sen;
  114. let y1 = u * sen + v1 * cos;
  115. let x2 = u * cos - v2 * sen;
  116. let y2 = u * sen + v2 * cos;
  117. x1 = A.posX + x1;
  118. y1 = A.posY + y1;
  119. x2 = A.posX + x2;
  120. y2 = A.posY + y2;
  121. return [
  122. new IntersectionModel(x1, y1, undefined, this, circumference, true, 0),
  123. new IntersectionModel(x2, y2, undefined, this, circumference, true, 1)
  124. ];
  125. }
  126. /// Get Intersection Poin By Circumference and Line Segment
  127. /// @param {LineSegmentModel } lineSegment
  128. getIntersectionByLine (lineSegment) {
  129. const pointA = lineSegment.pointA, pointB = lineSegment.pointB; // sl = segment(A,B)
  130. const center = this.center, radius = this.getRadiusValue(); // c0 = circunference(C,A) = circ("center,radius")
  131. const dx = pointB.posX - pointA.posX;
  132. const dy = pointB.posY - pointA.posY;
  133. const cx = center.posX - pointA.posX;
  134. const cy = center.posY - pointA.posY;
  135. const a = dx * dx + dy * dy;
  136. const b = dx * cx + dy * cy;
  137. const c = cx * cx + cy * cy - radius * radius;
  138. const D = b / a;
  139. const q = c / a;
  140. const delta = D * D - q;
  141. const PA = new IntersectionModel(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 0);
  142. const PB = new IntersectionModel(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 1);
  143. if (delta < 0) {
  144. return [PA, PB];
  145. }
  146. const deltaSqrt = Math.sqrt(delta);
  147. const root1 = -D + deltaSqrt;
  148. const root2 = -D - deltaSqrt;
  149. const x1 = pointA.posX - dx * root1
  150. const y1 = pointA.posY - dy * root1;
  151. if (delta == 0) {
  152. PA.bind(x1, y1, undefined, lineSegment, this, true, 0);
  153. return [PA, PB];
  154. }
  155. const x2 = pointA.posX - dx * root2;
  156. const y2 = pointA.posY - dy * root2;
  157. PA.bind(x1, y1, undefined, lineSegment, this, true, 0);
  158. PB.bind(x2, y2, undefined, lineSegment, this, true, 1);
  159. if (this.visible) {
  160. if (!this.insideSegment(PA.posX, PA.posY))
  161. PA.bind(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 0)
  162. if (!this.insideSegment(PB.posX, PB.posY))
  163. PB.bind(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 1)
  164. }
  165. return [PA, PB];
  166. }
  167. // Verify intersection using "level set"
  168. insideSegment (intersecX, intersecY) {
  169. const valuesR = this.getDirection();
  170. const dirX = valuesR[0];
  171. const dirY = valuesR[1];
  172. const cInterA = dirX * intersecX + dirY * intersecY;
  173. // comparaca cv do ponto A > cv da intersec => vazio
  174. const cRA = dirX * this.center.posX + dirY * this.center.posY;
  175. if (cInterA < cRA) {
  176. return false;
  177. }
  178. // comparaca cv do ponto B < cv da intersec => vazio
  179. const cRB = dirX * this.radius.posX + dirY * this.radius.posY;
  180. if (cInterA > cRB) {
  181. this.posX = Number.MAX_SAFE_INTEGER;
  182. this.posY = Number.MAX_SAFE_INTEGER;
  183. return false;
  184. }
  185. return true;
  186. }
  187. static do (map, vecIdObj, list) {
  188. const id = map.get("id");
  189. const centerId = map.get("param")[0];
  190. const radiusId = map.get("param")[1];
  191. // const center = list.find(x => x.id === centerId);
  192. // const radius = list.find(x => x.id === radiusId);
  193. const index_center = GeometricObject.findOD(vecIdObj, centerId); // get the index of vecIdObj[ii].id == centerId
  194. const index_radius = GeometricObject.findOD(vecIdObj, radiusId); // get the index of vecIdObj[ii].id == radiusId
  195. const center = list[index_center]; // center Point
  196. const radius = list[index_radius]; // Point defining circumference radius
  197. const label = map.get("label")[0];
  198. const circumference = new CircumferenceModel(center, radius, id);
  199. circumference.setLabel(label);
  200. return circumference;
  201. }
  202. } // export class CircumferenceModel extends GeometricObject