circumference-model.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. /* Deixar mais intuitiva...
  35. this._coordinates[0] = this.center.posX;
  36. this._coordinates[1] = this.center.posY;
  37. this._coordinates[2] = this.radius.posX;
  38. this._coordinates[3] = this.radius.posY;
  39. const legA = this._coordinates[2] - this._coordinates[0];
  40. const legB = this._coordinates[3] - this._coordinates[1];
  41. const radius = Math.sqrt(Math.pow(legA, 2) + Math.pow(legB, 2)); // Desnecessario!
  42. return radius;
  43. */
  44. var Cx, Cy, Ax, Ay;
  45. Cx = this._coordinates[0] = this.center.posX;
  46. Cy = this._coordinates[1] = this.center.posY;
  47. Ax = this._coordinates[2] = this.radius.posX;
  48. Ay = this._coordinates[3] = this.radius.posY;
  49. //D console.log("circumference-model.js: circ((" + Cx +","+ Cy +"), ("+Ax+","+Ay+")");
  50. const dx = Ax - Cx;
  51. const dy = Ay - Cy;
  52. const radius = Math.sqrt(dx * dx + dy * dy);
  53. return radius;
  54. }
  55. getStraight() {
  56. const dx = this.radius.posX - this.center.posX;
  57. const dy = this.radius.posY - this.center.posY;
  58. const c = Math.sqrt(dy * dy + dx * dx);
  59. return [dx, dy, c];
  60. }
  61. getDirection() {
  62. const aX = this.center.posX;
  63. const aY = this.center.posY;
  64. const bX = this.radius.posX;
  65. const bY = this.radius.posY;
  66. const a = bX - aX;
  67. const b = bY - aY;
  68. return [a, b];
  69. }
  70. getIntersection(geometricObject) {
  71. switch (geometricObject.elementClass) {
  72. case ELEMENTS_CLASS.LINE: // StraightLine
  73. return geometricObject.getIntersectionWithCircumference(this); // Delegate to StraightLine
  74. case ELEMENTS_CLASS.LINE_SEGMENT:
  75. return this.getIntersectionByLine(geometricObject); //TODO melhor 'with' que 'by'
  76. case ELEMENTS_CLASS.CIRCUMFERENCE:
  77. return this.getIntersectionsByCircumference(geometricObject); //TODO melhor 'with' que 'by'
  78. default:
  79. break;
  80. }
  81. }
  82. distance(center) {
  83. const dx = center.posX - this.center.posX;
  84. const dy = center.posY - this.center.posY;
  85. const dist = Math.sqrt(dy * dy + dx * dx);
  86. return dist;
  87. }
  88. getIntersectionsByCircumference(circumference) {
  89. //TODO if (this.cente().igual(cd.C())) return null; // duas circ. com mesmo raio => devolva "null" (ambiguidade!)
  90. const r1 = this.getRadius(); // raio circ. atual
  91. const r2 = circumference.getRadius(); // raio circ. "cd"
  92. const d = this.distance(circumference); // distancia entre os raios das circ.
  93. if (r1 + r2 < d || Math.abs(r1 - r2) > d) return null;
  94. const A = this.center; // pega o centro da circunferencia atual
  95. const B = circumference.center; // pega o centro da circunferencia "cd"
  96. const x = B.posX - A.posX;
  97. const y = B.posY - A.posY;
  98. 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|)
  99. let sen = Math.sqrt(1 - cos * cos);
  100. if (A.posY > B.posY) sen = -sen;
  101. let u1 = B.posX - A.posX;
  102. let v1 = B.posY - A.posY;
  103. let u = u1 * cos + v1 * sen;
  104. let v = -u1 * sen + v1 * cos;
  105. const rA = this.getRadius();
  106. const rB = circumference.getRadius();
  107. u = (u * u - rB * rB + rA * rA) / (2 * u);
  108. v = Math.sqrt(rA * rA - u * u);
  109. v1 = v;
  110. let v2 = -v;
  111. let x1 = u * cos - v1 * sen;
  112. let y1 = u * sen + v1 * cos;
  113. let x2 = u * cos - v2 * sen;
  114. let y2 = u * sen + v2 * cos;
  115. x1 = A.posX + x1;
  116. y1 = A.posY + y1;
  117. x2 = A.posX + x2;
  118. y2 = A.posY + y2;
  119. return [
  120. new IntersectionModel(x1, y1, undefined, this, circumference, true, 0),
  121. new IntersectionModel(x2, y2, undefined, this, circumference, true, 1)
  122. ];
  123. }
  124. /// Get Intersection Poin By Circumference and Line Segment
  125. /// @param {LineSegmentModel } lineSegment
  126. getIntersectionByLine(lineSegment) {
  127. const pointA = lineSegment.pointA, pointB = lineSegment.pointB; // sl = segment(A,B)
  128. const center = this.center, radius = this.getRadius(); // c0 = circunference(C,A) = circ("center,radius")
  129. const dx = pointB.posX - pointA.posX;
  130. const dy = pointB.posY - pointA.posY;
  131. const cx = center.posX - pointA.posX;
  132. const cy = center.posY - pointA.posY;
  133. const a = dx * dx + dy * dy;
  134. const b = dx * cx + dy * cy;
  135. const c = cx * cx + cy * cy - radius * radius;
  136. const D = b / a;
  137. const q = c / a;
  138. const delta = D * D - q;
  139. const PA = new IntersectionModel(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 0);
  140. const PB = new IntersectionModel(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 1);
  141. if (delta < 0) {
  142. return [PA, PB];
  143. }
  144. const deltaSqrt = Math.sqrt(delta);
  145. const root1 = -D + deltaSqrt;
  146. const root2 = -D - deltaSqrt;
  147. const x1 = pointA.posX - dx * root1
  148. const y1 = pointA.posY - dy * root1;
  149. if (delta == 0) {
  150. PA.bind(x1, y1, undefined, lineSegment, this, true, 0);
  151. return [PA, PB];
  152. }
  153. const x2 = pointA.posX - dx * root2;
  154. const y2 = pointA.posY - dy * root2;
  155. PA.bind(x1, y1, undefined, lineSegment, this, true, 0);
  156. PB.bind(x2, y2, undefined, lineSegment, this, true, 1);
  157. if (this.visible) {
  158. if (!this.insideSegment(PA.posX, PA.posY))
  159. PA.bind(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 0)
  160. if (!this.insideSegment(PB.posX, PB.posY))
  161. PB.bind(Number.MAX_SAFE_INTEGER, Number.MAX_SAFE_INTEGER, undefined, lineSegment, this, false, 1)
  162. }
  163. return [PA, PB];
  164. }
  165. // Verify intersection using "level set"
  166. insideSegment(intersecX, intersecY) {
  167. const valuesR = this.getDirection();
  168. const dirX = valuesR[0];
  169. const dirY = valuesR[1];
  170. const cInterA = dirX * intersecX + dirY * intersecY;
  171. // comparaca cv do ponto A > cv da intersec => vazio
  172. const cRA = dirX * this.center.posX + dirY * this.center.posY;
  173. if (cInterA < cRA) {
  174. return false;
  175. }
  176. // comparaca cv do ponto B < cv da intersec => vazio
  177. const cRB = dirX * this.radius.posX + dirY * this.radius.posY;
  178. if (cInterA > cRB) {
  179. this.posX = Number.MAX_SAFE_INTEGER;
  180. this.posY = Number.MAX_SAFE_INTEGER;
  181. return false;
  182. }
  183. return true;
  184. }
  185. static do(map, list) {
  186. const id = map.get("id");
  187. const centerId = map.get("param")[0];
  188. const radiusId = map.get("param")[1];
  189. const center = list.find(x => x.id === centerId);
  190. const radius = list.find(x => x.id === radiusId);
  191. const label = map.get("label")[0];
  192. const circumference = new CircumferenceModel(center, radius, id);
  193. circumference.setLabel(label);
  194. return circumference;
  195. }
  196. }