图书馆智能管理系统
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
8.6 KiB

5 months ago
  1. /* Copyright 2005-2015 Alfresco Software, Ltd.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. /**
  16. * Class to generate polyline
  17. *
  18. * @author Dmitry Farafonov
  19. */
  20. var ANCHOR_TYPE= {
  21. main: "main",
  22. middle: "middle",
  23. first: "first",
  24. last: "last"
  25. };
  26. function Anchor(uuid, type, x, y) {
  27. this.uuid = uuid;
  28. this.x = x;
  29. this.y = y;
  30. this.type = (type == ANCHOR_TYPE.middle) ? ANCHOR_TYPE.middle : ANCHOR_TYPE.main;
  31. };
  32. Anchor.prototype = {
  33. uuid: null,
  34. x: 0,
  35. y: 0,
  36. type: ANCHOR_TYPE.main,
  37. isFirst: false,
  38. isLast: false,
  39. ndex: 0,
  40. typeIndex: 0
  41. };
  42. function Polyline(uuid, points, strokeWidth, paper) {
  43. /* Array on coordinates:
  44. * points: [{x: 410, y: 110}, 1
  45. * {x: 570, y: 110}, 1 2
  46. * {x: 620, y: 240}, 2 3
  47. * {x: 750, y: 270}, 3 4
  48. * {x: 650, y: 370}]; 4
  49. */
  50. this.points = points;
  51. /*
  52. * path for graph
  53. * [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]]
  54. */
  55. this.path = [];
  56. this.anchors = [];
  57. if (strokeWidth) this.strokeWidth = strokeWidth;
  58. this.paper = paper;
  59. this.closePath = false;
  60. this.init();
  61. };
  62. Polyline.prototype = {
  63. id: null,
  64. points: [],
  65. path: [],
  66. anchors: [],
  67. strokeWidth: 1,
  68. radius: 1,
  69. showDetails: false,
  70. paper: null,
  71. element: null,
  72. isDefaultConditionAvailable: false,
  73. closePath: false,
  74. init: function(points){
  75. var linesCount = this.getLinesCount();
  76. if (linesCount < 1)
  77. return;
  78. this.normalizeCoordinates();
  79. // create anchors
  80. this.pushAnchor(ANCHOR_TYPE.first, this.getLine(0).x1, this.getLine(0).y1);
  81. for (var i = 1; i < linesCount; i++)
  82. {
  83. var line1 = this.getLine(i-1);
  84. this.pushAnchor(ANCHOR_TYPE.main, line1.x2, line1.y2);
  85. }
  86. this.pushAnchor(ANCHOR_TYPE.last, this.getLine(linesCount-1).x2, this.getLine(linesCount-1).y2);
  87. this.rebuildPath();
  88. },
  89. normalizeCoordinates: function(){
  90. for(var i=0; i < this.points.length; i++){
  91. this.points[i].x = parseFloat(this.points[i].x);
  92. this.points[i].y = parseFloat(this.points[i].y);
  93. }
  94. },
  95. getLinesCount: function(){
  96. return this.points.length-1;
  97. },
  98. _getLine: function(i){
  99. if (this.points.length > i && this.points[i]) {
  100. return {x1: this.points[i].x, y1: this.points[i].y, x2: this.points[i+1].x, y2: this.points[i+1].y};
  101. } else {
  102. return undefined;
  103. }
  104. },
  105. getLine: function(i){
  106. var line = this._getLine(i);
  107. if (line != undefined) {
  108. line.angle = this.getLineAngle(i);
  109. }
  110. return line;
  111. },
  112. getLineAngle: function(i){
  113. var line = this._getLine(i);
  114. return Math.atan2(line.y2 - line.y1, line.x2 - line.x1);
  115. },
  116. getLineLengthX: function(i){
  117. var line = this.getLine(i);
  118. return (line.x2 - line.x1);
  119. },
  120. getLineLengthY: function(i){
  121. var line = this.getLine(i);
  122. return (line.y2 - line.y1);
  123. },
  124. getLineLength: function(i){
  125. return Math.sqrt(Math.pow(this.getLineLengthX(i), 2) + Math.pow(this.getLineLengthY(i), 2));
  126. },
  127. getAnchors: function(){
  128. return this.anchors;
  129. },
  130. getAnchorsCount: function(type){
  131. if (!type)
  132. return this.anchors.length;
  133. else {
  134. var count = 0;
  135. for(var i=0; i < this.getAnchorsCount(); i++){
  136. var anchor = this.anchors[i];
  137. if (anchor.getType() == type) {
  138. count++;
  139. }
  140. }
  141. return count;
  142. }
  143. },
  144. pushAnchor: function(type, x, y, index){
  145. if (type == ANCHOR_TYPE.first) {
  146. index = 0;
  147. typeIndex = 0;
  148. } else if (type == ANCHOR_TYPE.last) {
  149. index = this.getAnchorsCount();
  150. typeIndex = 0;
  151. } else if (!index) {
  152. index = this.anchors.length;
  153. } else {
  154. for(var i=0; i < this.getAnchorsCount(); i++){
  155. var anchor = this.anchors[i];
  156. if (anchor.index > index) {
  157. anchor.index++;
  158. anchor.typeIndex++;
  159. }
  160. }
  161. }
  162. var anchor = new Anchor(this.id, ANCHOR_TYPE.main, x, y, index, typeIndex);
  163. this.anchors.push(anchor);
  164. },
  165. getAnchor: function(position){
  166. return this.anchors[position];
  167. },
  168. getAnchorByType: function(type, position){
  169. if (type == ANCHOR_TYPE.first)
  170. return this.anchors[0];
  171. if (type == ANCHOR_TYPE.last)
  172. return this.anchors[this.getAnchorsCount()-1];
  173. for(var i=0; i < this.getAnchorsCount(); i++){
  174. var anchor = this.anchors[i];
  175. if (anchor.type == type) {
  176. if( position == anchor.position)
  177. return anchor;
  178. }
  179. }
  180. return null;
  181. },
  182. addNewPoint: function(position, x, y){
  183. //
  184. for(var i = 0; i < this.getLinesCount(); i++){
  185. var line = this.getLine(i);
  186. if (x > line.x1 && x < line.x2 && y > line.y1 && y < line.y2) {
  187. this.points.splice(i+1,0,{x: x, y: y});
  188. break;
  189. }
  190. }
  191. this.rebuildPath();
  192. },
  193. rebuildPath: function(){
  194. var path = [];
  195. for(var i = 0; i < this.getAnchorsCount(); i++){
  196. var anchor = this.getAnchor(i);
  197. var pathType = "";
  198. if (i == 0)
  199. pathType = "M";
  200. else
  201. pathType = "L";
  202. // TODO: save previous points and calculate new path just if points are updated, and then save currents values as previous
  203. var targetX = anchor.x, targetY = anchor.y;
  204. if (i>0 && i < this.getAnchorsCount()-1) {
  205. // get new x,y
  206. var cx = anchor.x, cy = anchor.y;
  207. // pivot point of prev line
  208. var AO = this.getLineLength(i-1);
  209. if (AO < this.radius) {
  210. AO = this.radius;
  211. }
  212. this.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));
  213. var ED = this.getLineLengthY(i-1) * this.radius / AO;
  214. var OD = this.getLineLengthX(i-1) * this.radius / AO;
  215. targetX = anchor.x - OD;
  216. targetY = anchor.y - ED;
  217. if (AO < 2*this.radius && i>1) {
  218. targetX = anchor.x - this.getLineLengthX(i-1)/2;
  219. targetY = anchor.y - this.getLineLengthY(i-1)/2;;
  220. }
  221. // pivot point of next line
  222. var AO = this.getLineLength(i);
  223. if (AO < this.radius) {
  224. AO = this.radius;
  225. }
  226. var ED = this.getLineLengthY(i) * this.radius / AO;
  227. var OD = this.getLineLengthX(i) * this.radius / AO;
  228. var nextSrcX = anchor.x + OD;
  229. var nextSrcY = anchor.y + ED;
  230. if (AO < 2*this.radius && i<this.getAnchorsCount()-2) {
  231. nextSrcX = anchor.x + this.getLineLengthX(i)/2;
  232. nextSrcY = anchor.y + this.getLineLengthY(i)/2;;
  233. }
  234. var dx0 = (cx - targetX) / 3,
  235. dy0 = (cy - targetY) / 3,
  236. ax = cx - dx0,
  237. ay = cy - dy0,
  238. dx1 = (cx - nextSrcX) / 3,
  239. dy1 = (cy - nextSrcY) / 3,
  240. bx = cx - dx1,
  241. by = cy - dy1,
  242. zx=nextSrcX, zy=nextSrcY;
  243. } else if (i==1 && this.getAnchorsCount() == 2){
  244. var AO = this.getLineLength(i-1);
  245. if (AO < this.radius) {
  246. AO = this.radius;
  247. }
  248. this.isDefaultConditionAvailable = (this.isDefaultConditionAvailable || (i == 1 && AO > 10));
  249. }
  250. // anti smoothing
  251. if (this.strokeWidth%2 == 1) {
  252. targetX += 0.5;
  253. targetY += 0.5;
  254. }
  255. path.push([pathType, targetX, targetY]);
  256. if (i>0 && i < this.getAnchorsCount()-1) {
  257. path.push(["C", ax, ay, bx, by, zx, zy]);
  258. }
  259. }
  260. if (this.closePath)
  261. {
  262. path.push(["Z"]);
  263. }
  264. this.path = path;
  265. },
  266. transform: function(transformation)
  267. {
  268. this.element.transform(transformation);
  269. },
  270. attr: function(attrs)
  271. {
  272. // TODO: foreach and set each
  273. this.element.attr(attrs);
  274. }
  275. };
  276. function Polygone(points, strokeWidth) {
  277. /* Array on coordinates:
  278. * points: [{x: 410, y: 110}, 1
  279. * {x: 570, y: 110}, 1 2
  280. * {x: 620, y: 240}, 2 3
  281. * {x: 750, y: 270}, 3 4
  282. * {x: 650, y: 370}]; 4
  283. */
  284. this.points = points;
  285. /*
  286. * path for graph
  287. * [["M", x1, y1], ["L", x2, y2], ["C", ax, ay, bx, by, x3, y3], ["L", x3, y3]]
  288. */
  289. this.path = [];
  290. this.anchors = [];
  291. if (strokeWidth) this.strokeWidth = strokeWidth;
  292. this.closePath = true;
  293. this.init();
  294. };
  295. /*
  296. * Poligone is inherited from Poliline: draws closedPath of polyline
  297. */
  298. var Foo = function () { };
  299. Foo.prototype = Polyline.prototype;
  300. Polygone.prototype = new Foo();
  301. Polygone.prototype.rebuildPath = function(){
  302. var path = [];
  303. for(var i = 0; i < this.getAnchorsCount(); i++){
  304. var anchor = this.getAnchor(i);
  305. var pathType = "";
  306. if (i == 0)
  307. pathType = "M";
  308. else
  309. pathType = "L";
  310. var targetX = anchor.x, targetY = anchor.y;
  311. // anti smoothing
  312. if (this.strokeWidth%2 == 1) {
  313. targetX += 0.5;
  314. targetY += 0.5;
  315. }
  316. path.push([pathType, targetX, targetY]);
  317. }
  318. if (this.closePath)
  319. path.push(["Z"]);
  320. this.path = path;
  321. };