circumference-model.js 6.5 KB

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