smooth.js 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914
  1. /**
  2. * Created by Administrator on 2015/5/22.
  3. */
  4. define([], function(){
  5. var xnew;
  6. var ynew;
  7. var sizenew;
  8. var addNewPointFlag;
  9. //线条平滑 ----二维数组
  10. function smoothLine(arrs,interval,distance){
  11. var points=getPositionFromDistance(arrs,distance);
  12. if(points) {
  13. var ps=points//getSmoothPositionFromAngle(points,0);
  14. var xs = [];
  15. var ys = [];
  16. for (var i = 0; i < ps.length; i++) {
  17. xs.push(parseFloat(ps[i][0]||ps[i].x));
  18. ys.push(parseFloat(ps[i][1]||ps[i].y));
  19. }
  20. return smooth(xs, ys, interval);
  21. }else{
  22. //console.log("没有平滑,抽取失败");
  23. return arrs;
  24. }
  25. }
  26. /**
  27. * 间隔 样条平滑
  28. * @param x 横坐标
  29. * @param y 纵坐标
  30. * @param interval 间隔
  31. * @return 二维数组 第一纬为x 第二维为y
  32. */
  33. function smooth( x, y,interval) {
  34. var result = new Array(2);
  35. if (x == null || y == null || x.length != y.length) {
  36. result[0] = x;
  37. result[1] = y;
  38. return _formatPoint(result[0],result[1]);
  39. }
  40. var isClosed = false;
  41. if (x[0] == x[x.length - 1] && y[0] == y[y.length - 1]) {
  42. isClosed = true;
  43. }
  44. if (!isClosed) {
  45. var splineCount = getSplinePointCount(x, y, interval);
  46. result[0] = new Array(splineCount);
  47. result[1] = new Array(splineCount);
  48. splineProc(x, y, interval, result[0], result[1]);
  49. return _formatPoint(result[0],result[1]);
  50. }
  51. //处理闭合曲线 控制角度120
  52. // var angleBounder = 120;
  53. // var remark = 1;
  54. // for (remark = 1; remark < x.length - 1; remark++) {
  55. // if (getAngle(x[remark - 1] - x[remark], y[remark - 1] - y[remark],
  56. // x[remark + 1] - x[remark], y[remark + 1] - y[remark]) > angleBounder) {
  57. // break;
  58. // }
  59. // }
  60. // if (remark == x.length - 1) {
  61. // remark = 0;//不处理
  62. // }
  63. // var newX = shiftArray(x, remark);
  64. // var newY = shiftArray(y, remark);
  65. var splineCount = getSplinePointCount(x, y, interval);
  66. if(splineCount.length<= x.length){
  67. return _formatPoint(x,y);
  68. }
  69. result[0] = new Array(splineCount);
  70. result[1] = new Array(splineCount);
  71. splineProc(x, y, interval, result[0], result[1]);
  72. return _formatPoint(result[0],result[1]);
  73. }
  74. /**
  75. * 获取插值平滑后输出的点数
  76. * @param x 横坐标
  77. * @param y 纵坐标
  78. * @param interval 间隔
  79. * @return 个数
  80. */
  81. function getSplinePointCount(x, y, interval) {
  82. // 计算距离
  83. if (x.length != y.length) {
  84. ////console.log("x长度:" + x.length + ", y长度:" + y.length);
  85. ////console.log("In MIDS3DMath.getSplinePointCount()中输入的x y的长度不同");
  86. }
  87. if (x.length <= 2 || y.length <= 2) {
  88. ////console.log("x、y的个数太少,无法插值");
  89. return x.length;
  90. }
  91. var size = x.length;
  92. var dis = new Array(size-1);
  93. var dmin = 0.0;
  94. var dmax = 0.0;
  95. // [-180,180]转换为[0,360]
  96. for (var i = 0; i < size; i++) {
  97. if (x[i] < -1e-10) {
  98. x[i] = x[i] + 360.0;
  99. }
  100. }
  101. for (var i = 0; i < size - 1; i++) {
  102. var tmp = (x[i + 1] - x[i]) * (x[i + 1] - x[i])
  103. + (y[i + 1] - y[i]) * (y[i + 1] - y[i]);
  104. if (tmp != 0.0) {
  105. dmin = tmp;
  106. dmax = tmp;
  107. // break;
  108. }
  109. }
  110. if (dmin == 0.0 || dmax == 0.0) {
  111. //console.log("相邻两点间, 最小距离:" + dmin + "; 最大距离:" + dmax);
  112. //console.log("In MIDS3DMath.getSplinePointCount()中输入的点相同");
  113. }
  114. // 找到相邻两点之间的最大最小距离
  115. for (var i = 0; i < size - 1; i++) {
  116. dis[i] = (x[i + 1] - x[i]) * (x[i + 1] - x[i]) + (y[i + 1] - y[i])
  117. * (y[i + 1] - y[i]);
  118. if (dis[i] > dmax) {
  119. dmax = dis[i];
  120. }
  121. if (dis[i] < dmin && dis[i] != 0.0) {
  122. dmin = dis[i];
  123. }
  124. }
  125. var xinsert = [];
  126. var yinsert = [];
  127. addNewPointFlag = false;
  128. var MAXINTERVAL = 2000;// 两点之间最大最小距离>2000倍的时候不插值
  129. var MAXMINRATE = 6;// 两点之间最大最小距离小于6倍的不需要增加点,可直接进行插值
  130. var CURPTMINRATE = 4;// 当前点和最小距离之间的倍数小于4时,不增加点,4~8倍增加一个点,8~12倍增加两个点...
  131. for (var i = 0; i < size - 1; i++) {
  132. if (dmax < MAXMINRATE * MAXMINRATE * dmin) {
  133. break;
  134. }
  135. addNewPointFlag = true;
  136. xinsert.push(x[i]);
  137. yinsert.push(y[i]);
  138. var yytmp = y[i + 1] - y[i];
  139. var xxtmp = x[i + 1] - x[i];
  140. for (var j = 1; j < MAXINTERVAL / CURPTMINRATE; j++) {
  141. if (dis[i] <= CURPTMINRATE * CURPTMINRATE * dmin) {
  142. break;
  143. }
  144. if (dis[i] > j * j * CURPTMINRATE * CURPTMINRATE * dmin
  145. && dis[i] <= (j + 1) * (j + 1) * CURPTMINRATE
  146. * CURPTMINRATE * dmin) {
  147. for (var k = 1; k <= j; k++) {
  148. var xtmp;
  149. var ytmp;
  150. if (yytmp == 0.0) {
  151. xtmp = x[i] + k * xxtmp / (j + 1);
  152. ytmp = y[i];
  153. } else {
  154. if (xxtmp == 0.0) {
  155. xtmp = x[i];
  156. ytmp = y[i] + k * yytmp / (j + 1);
  157. } else {
  158. xtmp = x[i] + k * xxtmp / (j + 1);
  159. ytmp = y[i] + k * yytmp / (j + 1);
  160. }
  161. }
  162. xinsert.push(xtmp);
  163. yinsert.push(ytmp);
  164. }
  165. break;
  166. }
  167. }
  168. if (dis[i] > MAXINTERVAL * MAXINTERVAL * dmin) {
  169. //console.log("x[" + i + "] = " + x[i] + ", y[" + i + "] = " + y[i]);
  170. //console.log("x[" + (i + 1) + "] = " + x[i + 1] + ", y[" + (i + 1) + "] = " + y[i + 1]);
  171. //console.log("以上两点之间的距离dis = " + dis[i]);
  172. //console.log("最小距离dmin = " + dmin);
  173. //console.log("In MIDS3DMath.getSplinePointCount()存在相邻两点之间的距离太大,插值不准确,请重新选择点");
  174. return 0;
  175. // throw new
  176. // RuntimeErrorException(null,"In MIDS3DMath.getSplinePointCount()存在相邻两点之间的距离太大,插值不准确,请重新选择点");
  177. }
  178. }// end for
  179. if (addNewPointFlag) {
  180. xinsert.push(x[size - 1]);
  181. yinsert.push(y[size - 1]);
  182. }
  183. if (xinsert.length!=0) {
  184. if (xinsert.length != yinsert.length) {
  185. //console.log("In MIDS3DMath.getSplinePointCount()增加的点的x y个数不同");
  186. }
  187. }
  188. if (xinsert.length==0) {
  189. sizenew = size;
  190. xnew = new Array(size);
  191. xnew = x;
  192. ynew = new Array(size);
  193. ynew = y;
  194. } else {
  195. sizenew = xinsert.length;
  196. xnew = new Array(sizenew);
  197. ynew = new Array(sizenew);
  198. for (var i = 0; i < sizenew; i++) {
  199. xnew[i] = xinsert[i];
  200. ynew[i] = yinsert[i];
  201. }
  202. }
  203. var xShift = new Array(sizenew);
  204. var yShift = new Array(sizenew);
  205. var t = new Array(sizenew);
  206. var index = [];
  207. for (var i = 0; i < sizenew; i++) {
  208. if (i == 0) {
  209. xShift[i] = xnew[sizenew - 1];
  210. yShift[i] = ynew[sizenew - 1];
  211. } else {
  212. xShift[i] = xnew[i - 1];
  213. yShift[i] = ynew[i - 1];
  214. }
  215. t[i] = Math.sqrt((xnew[i] - xShift[i])
  216. * (xnew[i] - xShift[i]) + (ynew[i] - yShift[i])
  217. * (ynew[i] - yShift[i]));
  218. if (i > 0 && t[i] > 0.0) {
  219. index.push(i);
  220. }
  221. }
  222. t[0] = 0.0;
  223. if (index.length==0) {
  224. return 0;
  225. }
  226. var length = index.length + 1;
  227. var xx = new Array(length);
  228. var yy = new Array(length);
  229. var tt = new Array(length);
  230. var r = 0;
  231. var rr = new Array(length);
  232. var kk = 0;
  233. for (var i = 0; i < length; i++) {
  234. if (i == 0) {
  235. xx[i] = xnew[0];
  236. yy[i] = ynew[0];
  237. tt[i] = t[0];
  238. } else {
  239. xx[i] = xnew[index[kk]];
  240. yy[i] = ynew[index[kk]];
  241. tt[i] = t[index[kk]];
  242. kk++;
  243. }
  244. rr[i] = (Math.ceil(tt[i] / interval));
  245. r = parseInt(r + rr[i]);
  246. }
  247. return r + 1;
  248. }
  249. /**
  250. * 线条平滑
  251. * @param x 横坐标
  252. * @param y 纵坐标
  253. * @param interval 间隔
  254. * @param xout 输出插值完成的横坐标
  255. * @param yout 输出插值完成的纵坐标
  256. * @return 插值平滑成功返回true,否则false
  257. */
  258. function splineProc( x, y, interval,
  259. xout, yout) {
  260. if (xout.length == 0 || yout.length == 0) {
  261. return [x,y];
  262. }
  263. if (x == null || y == null) {
  264. //console.log("x或y为null");
  265. return [x,y];
  266. }
  267. if (x.length != y.length) {
  268. ////console.log("x长度:" + x.length + ", y长度:" + y.length);
  269. ////console.log("In MIDS3DMath.getSplinePointCount()中输入的x y的长度不同");
  270. }
  271. if (x.length <= 2 || y.length <= 2) {
  272. ////console.log("x、y的个数太少,无法插值");
  273. xout = x;
  274. yout = y;
  275. return [x,y];
  276. }
  277. // [-180,180]转换为[0,360]
  278. for (var i = 0; i < x.length; i++) {
  279. if (x[i] < 1e-10) {
  280. x[i] = x[i] + 360.0;
  281. }
  282. }
  283. if (!addNewPointFlag) {
  284. var xSize = x.length;
  285. var ySize = y.length;
  286. if (xSize != ySize) {
  287. //console.log("In MIDS3DMath.splineProcAry()中输入的x,y点的个数不同");
  288. return false;
  289. }
  290. if (xSize <= 2) {
  291. //console.log("In MIDSMath.splineProcAry()中x,y的个数太少,不满足平滑条件,按原值返回");
  292. xout = x;
  293. yout = y;
  294. return true;
  295. }
  296. var size = xSize;
  297. var xShift = new Array(size);
  298. var yShift = new Array(size);
  299. var t = new Array(size);
  300. var index = [];
  301. for (var i = 0; i < x.length; i++) {
  302. if (i == 0) {
  303. xShift[i] = x[size - 1];
  304. yShift[i] = y[size - 1];
  305. } else {
  306. xShift[i] = x[i - 1];
  307. yShift[i] = y[i - 1];
  308. }
  309. t[i] = Math.sqrt((x[i] - xShift[i])
  310. * (x[i] - xShift[i]) + (y[i] - yShift[i])
  311. * (y[i] - yShift[i]));
  312. if (i > 0 && t[i] > 0.0) {
  313. index.push(i);
  314. }
  315. }
  316. t[0] = 0.0;
  317. if (index.length==0 || index.length < 2) {
  318. return false;
  319. }
  320. var length = index.length + 1;
  321. var xx = new Array(length);
  322. var yy = new Array(length);
  323. var tt = new Array(length);
  324. var r = 0;
  325. var rr = new Array(length);
  326. var kk = 0;
  327. for (var i = 0; i < length; i++) {
  328. if (i == 0) {
  329. xx[i] = x[0];
  330. yy[i] = y[0];
  331. tt[i] = t[0];
  332. } else {
  333. xx[i] = x[index[kk]];
  334. yy[i] = y[index[kk]];
  335. tt[i] = t[index[kk]];
  336. kk++;
  337. }
  338. rr[i] = Math.ceil(tt[i] / interval);
  339. r = parseInt(r + rr[i]);
  340. }
  341. var count = r + 1;
  342. if (xout.length < count){
  343. return false;
  344. }
  345. var ttt = new Array(count);
  346. var k;
  347. var j = 0;
  348. for (var i = 1; i < length; i++) {
  349. k = parseInt(rr[i]);
  350. for (var m = 0; m < k; m++) {
  351. ttt[parseInt(j + m)] = m * (tt[i] / k) + tt[i - 1];
  352. }
  353. tt[i] = tt[i] + tt[i - 1];
  354. j = j + k;
  355. }
  356. ttt[parseInt(j)] = tt[length - 1];
  357. var xp = new Array(count);
  358. var yp = new Array(count);
  359. xp = spline(tt, xx, ttt);
  360. yp = spline(tt, yy, ttt);
  361. // if (xout.length < count){
  362. // System.err.println("In MIDS3DMath splineProc...中 平滑后的元素xout的长度小于原始数据的长度!该线条进行样条平滑失败!");
  363. // return false;
  364. // }
  365. for (var i = 0; i < count; i++) {
  366. if (xp[i] - 180.0 > 1e-10) {
  367. xout[i] = xp[i] - 360.0;
  368. } else {
  369. xout[i] = xp[i];
  370. }
  371. yout[i] = yp[i];
  372. }
  373. if (xout.length != yout.length) {
  374. //console.log("In MIDS3DMath.splineProc()中平滑插值出的x,y值个数不同,出错");
  375. return false;
  376. }
  377. //如果是闭合线则必须保证首尾两点相等
  378. if(x[0]==x[x.length-1] && y[0]==y[y.length-1]){
  379. if(xout[0]!=xout[count-1]){
  380. xout[count-1]=xout[0];
  381. }
  382. if(yout[0]!=yout[count-1]){
  383. yout[count-1]=yout[0];
  384. }
  385. }
  386. xp = null;
  387. yp = null;
  388. return true;
  389. } else {
  390. var xSize = xnew.length;
  391. var ySize = ynew.length;
  392. if (xSize != ySize) {
  393. //console.log("In MIDS3DMath.splineProcAry()中输入的x,y点的个数不同");
  394. return false;
  395. }
  396. if (xSize <= 2) {
  397. //console.log("In MIDSMath.splineProcAry()中x,y的个数太少,不满足平滑条件,按原值返回");
  398. xout = xnew;
  399. yout = ynew;
  400. return true;
  401. }
  402. var size = xSize;
  403. var xShift = new Array(size);
  404. var yShift = new Array(size);
  405. var t = new Array(size);
  406. var index = [];
  407. for (var i = 0; i < size; i++) {
  408. if (i == 0) {
  409. xShift[i] = xnew[size - 1];
  410. yShift[i] = ynew[size - 1];
  411. } else {
  412. xShift[i] = xnew[i - 1];
  413. yShift[i] = ynew[i - 1];
  414. }
  415. t[i] = Math.sqrt((xnew[i] - xShift[i])
  416. * (xnew[i] - xShift[i]) + (ynew[i] - yShift[i])
  417. * (ynew[i] - yShift[i]));
  418. if (i > 0 && t[i] > 0.0) {
  419. index.push(i);
  420. }
  421. }
  422. t[0] = 0.0;
  423. if (index.length==0) {
  424. return false;
  425. }
  426. var length = index.length + 1;
  427. var xx = new Array(length);
  428. var yy = new Array(length);
  429. var tt = new Array(length);
  430. var r = 0;
  431. var rr = new Array(length);
  432. var kk = 0;
  433. for (var i = 0; i < length; i++) {
  434. if (i == 0) {
  435. xx[i] = xnew[0];
  436. yy[i] = ynew[0];
  437. tt[i] = t[0];
  438. } else {
  439. xx[i] = xnew[index[kk]];
  440. yy[i] = ynew[index[kk]];
  441. tt[i] = t[index[kk]];
  442. kk++;
  443. }
  444. rr[i] = Math.ceil(tt[i] / interval);
  445. r = parseInt(r + rr[i]);
  446. }
  447. var count = r + 1;
  448. var ttt = new Array(count);
  449. var k;
  450. var j = 0;
  451. for (var i = 1; i < length; i++) {
  452. k = parseInt(rr[i]);
  453. for (var m = 0; m < k; m++) {
  454. ttt[parseInt(j + m)] = m * (tt[i] / k) + tt[i - 1];
  455. }
  456. tt[i] = tt[i] + tt[i - 1];
  457. j = j + k;
  458. }
  459. ttt[parseInt(j)] = tt[length - 1];
  460. var xp = new Array(count);
  461. var yp = new Array(count);
  462. xp = spline(tt, xx, ttt);
  463. yp = spline(tt, yy, ttt);
  464. for (var i = 0; i < count; i++) {
  465. if (xp[i] - 180.0 > 1e-10) {
  466. xout[i] = xp[i] - 360.0;
  467. } else {
  468. xout[i] = xp[i];
  469. }
  470. yout[i] = yp[i];
  471. }
  472. if (xout.length != yout.length) {
  473. //console.log("In MIDS3DMath.splineProc()中平滑插值出的x,y值个数不同,出错");
  474. return false;
  475. }
  476. //如果是闭合线则必须保证首尾两点相等
  477. if(x[0]==x[x.length-1] && y[0]==y[y.length-1]){
  478. if(xout[0]!=xout[count-1]){
  479. xout[count-1]=xout[0];
  480. }
  481. if(yout[0]!=yout[count-1]){
  482. yout[count-1]=yout[0];
  483. }
  484. }
  485. xp = null;
  486. yp = null;
  487. return true;
  488. }
  489. }
  490. /**
  491. * @param x
  492. * @param y
  493. * @param t
  494. * @return
  495. */
  496. function spline( x, y, t) {
  497. var xLen = x.length;
  498. var yLen = y.length;
  499. var tLen = t.length;
  500. if (xLen != yLen) {
  501. //console.log("In MIDS3DMath.spline()中 X and Y must have same elements.");
  502. return null;
  503. }
  504. if (xLen <= 2) {
  505. //console.log("In MIDS3DMath.spline()中 X and Y must be arrays of 3 or more elements.");
  506. return null;
  507. }
  508. var size = xLen;
  509. var sigma = 1.0;
  510. var yp = new Array(2 * size);
  511. var delx1 = x[1] - x[0];
  512. var dx1 = (y[1] - y[0]) / delx1;
  513. var delx2 = x[2] - x[1];
  514. var delx12 = x[2] - x[0];
  515. var c1 = -(delx12 + delx1) / delx12 / delx1;
  516. var c2 = delx12 / delx1 / delx2;
  517. var c3 = -delx1 / delx12 / delx2;
  518. var slpp1 = c1 * y[0] + c2 * y[1] + c3 * y[2];
  519. var nm1 = size - 1;
  520. // var np1 = size + 1;
  521. var deln = x[nm1] - x[nm1 - 1];
  522. var delnm1 = x[nm1 - 1] - x[nm1 - 2];
  523. var delnn = x[nm1] - x[nm1 - 2];
  524. c1 = (delnn + deln) / delnn / deln;
  525. c2 = -delnn / deln / delnm1;
  526. c3 = deln / delnn / delnm1;
  527. var slppn = c3 * y[nm1 - 2] + c2 * y[nm1 - 1] + c1 * y[nm1];
  528. var sigmap = sigma * nm1 / (x[nm1] - x[0]);
  529. var dels = sigmap * delx1;
  530. var exps = Math.exp(dels);
  531. var sinhs = 0.5 * (exps - 1.0 / exps);
  532. var sinhin = 1.0 / (delx1 * sinhs);
  533. var diag1 = sinhin * (dels * 0.5 * (exps + 1.0 / exps) - sinhs);
  534. var diagin = 1.0 / diag1;
  535. yp[0] = diagin * (dx1 - slpp1);
  536. var spdiag = sinhin * (sinhs - dels);
  537. yp[size] = diagin * spdiag;
  538. var delxx2 = new Array(size-1);
  539. var delss = new Array(size-1);
  540. var dx2 = new Array(size-1);
  541. var expss = new Array(size-1);
  542. var sinhss = new Array(size-1);
  543. var sinhnn = new Array(size-1);
  544. var diag2 = new Array(size-1);
  545. var spdiagg = new Array(size-1);
  546. for (var i = 0; i < size - 1; i++) {
  547. delxx2[i] = x[i + 1] - x[i];
  548. dx2[i] = (y[i + 1] - y[i]) / delxx2[i];
  549. delss[i] = sigmap * delxx2[i];
  550. expss[i] = Math.exp(delss[i]);
  551. sinhss[i] = 0.5 * (expss[i] - 1.0 / expss[i]);
  552. sinhnn[i] = 1.0 / (delxx2[i] * sinhss[i]);
  553. diag2[i] = sinhnn[i]
  554. * (delss[i] * (0.5 * (expss[i] + 1.0/ expss[i])) - sinhss[i]);
  555. spdiagg[i] = sinhnn[i] * (sinhss[i] - delss[i]);
  556. }
  557. var dx2nm1 = dx2[nm1 - 1];
  558. var tmpdiag2 = new Array(size - 2);
  559. var tmpdx2 = new Array(size - 2);
  560. for (var i = size - 1 - 1 - 1; i >= 0; i--) {
  561. tmpdiag2[i] = diag2[i + 1];
  562. diag2[i + 1] = diag2[i] + tmpdiag2[i];
  563. tmpdx2[i] = dx2[i + 1];
  564. dx2[i + 1] = tmpdx2[i] - dx2[i];
  565. }
  566. diag2[0] = 0;
  567. dx2[0] = 0;
  568. for (var i = 1; i <= nm1 - 1; i++) {
  569. diagin = 1.0 / (diag2[i] - spdiagg[i - 1] * yp[i + size - 1]);
  570. yp[i] = diagin * (dx2[i] - spdiagg[i - 1] * yp[i - 1]);
  571. yp[i + size] =diagin * spdiagg[i];
  572. }
  573. diagin = 1.0 / (diag1 - spdiagg[nm1 - 1] * yp[size + nm1 - 1]);
  574. yp[nm1] = diagin * (slppn - dx2nm1 - spdiagg[nm1 - 1]
  575. * yp[nm1 - 1]);
  576. for (var i = size - 2; i >= 0; i--) {
  577. yp[i] = yp[i] - yp[i + size] * yp[i + 1];
  578. }
  579. var subs = new Array(tLen);
  580. for (var i = 0; i < tLen; i++) {
  581. subs[i] = nm1;
  582. }
  583. var s = x[nm1] - x[0];
  584. sigmap = sigma * nm1 / s;
  585. var j = 0;
  586. for (var i = 1; i <= nm1; i++) {
  587. while (t[j] < x[i]) {
  588. subs[j] = i;
  589. j++;
  590. if (j == tLen) {
  591. return getSplineData(tLen, subs, sigmap, x, y, t, yp);
  592. }
  593. }
  594. }
  595. return getSplineData(tLen, subs, sigmap, x, y, t, yp);
  596. }
  597. /**
  598. *
  599. * @param tLen
  600. * @param subs
  601. * @param sigmap
  602. * @param x
  603. * @param y
  604. * @param t
  605. * @param yp
  606. * @return
  607. */
  608. function getSplineData( tLen, subs, sigmap,
  609. x, y, t, yp) {
  610. /*var subs1 = new Array(tLen];
  611. var del1 = new Array(tLen];
  612. var del2 = new Array(tLen];
  613. var delss1 = new Array(tLen];
  614. var exps1 = new Array(tLen];
  615. var exps2 = new Array(tLen];
  616. var exps3 = new Array(tLen];
  617. var sinhd1 = new Array(tLen];
  618. var sinhd2 = new Array(tLen];
  619. var sinhs2 = new Array(tLen];
  620. var spl = new Array(tLen];
  621. for (var k = 0; k < tLen; k++) {
  622. subs1[k] = subs[k] - 1;
  623. del1[k] = t[k] - x[subs1[k]];
  624. del2[k] = x[subs[k]] - t[k];
  625. delss1[k] = x[subs[k]] - x[subs1[k]];
  626. exps1[k] = (var) Math.exp(sigmap * del1[k]);
  627. sinhd1[k] = 0.5f * (exps1[k] - 1.0f / exps1[k]);
  628. exps2[k] = (var) Math.exp(sigmap * del2[k]);
  629. sinhd2[k] = 0.5f * (exps2[k] - 1.0f / exps2[k]);
  630. exps3[k] = exps1[k] * exps2[k];
  631. sinhs2[k] = 0.5f * (exps3[k] - 1.0f / exps3[k]);
  632. spl[k] = (yp[subs[k]] * sinhd1[k] + yp[subs1[k]] * sinhd2[k]) / sinhs2[k]
  633. + ((y[subs[k]] - yp[subs[k]]) * del1[k] + (y[subs1[k]] - yp[subs1[k]]) * del2[k]) / delss1[k];
  634. }
  635. var spl2 = new var { spl[0] };
  636. return (tLen == 1) ? spl2 : spl;*/
  637. var subs1 = new Array(tLen);
  638. var del1 = new Array(tLen);
  639. var del2 = new Array(tLen);
  640. var delss1 = new Array(tLen);
  641. var exps1 = new Array(tLen);
  642. var exps2 = new Array(tLen);
  643. var exps3 = new Array(tLen);
  644. var sinhd1 = new Array(tLen);
  645. var sinhd2 = new Array(tLen);
  646. var sinhs2 = new Array(tLen);
  647. var spl = new Array(tLen);
  648. for (var k = 0; k < tLen; k++) {
  649. subs1[k] = subs[k] - 1;
  650. del1[k] = t[k] - x[subs1[k]];
  651. del2[k] = x[subs[k]] - t[k];
  652. delss1[k] = x[subs[k]] - x[subs1[k]];
  653. exps1[k] = Math.exp(sigmap * del1[k]);
  654. sinhd1[k] = 0.5 * (exps1[k] - 1 / exps1[k]);
  655. exps2[k] = Math.exp(sigmap * del2[k]);
  656. sinhd2[k] = 0.5 * (exps2[k] - 1 / exps2[k]);
  657. exps3[k] = exps1[k] * exps2[k];
  658. sinhs2[k] = 0.5 * (exps3[k] - 1 / exps3[k]);
  659. spl[k] = (yp[subs[k]] * sinhd1[k] + yp[subs1[k]] * sinhd2[k]) / sinhs2[k]
  660. + ((y[subs[k]] - yp[subs[k]]) * del1[k] + (y[subs1[k]] - yp[subs1[k]]) * del2[k]) / delss1[k];
  661. }
  662. return (tLen == 1) ? [spl[0]] : spl;
  663. }
  664. /**
  665. * 对一列有序的点根据距离间隔distance抽取大于此距离的点
  666. * @param linePos 有序点集合
  667. * @param distance 距离条件
  668. * @return 大于distance的点集
  669. */
  670. function getPositionFromDistance( linePos, distance) {
  671. if (linePos == null || linePos.length==0) {
  672. return null;
  673. }
  674. // System.out.println("原始点个数:" + linePos.size());
  675. var newPos = [];
  676. for(var i in linePos){
  677. newPos[i]=linePos[i];
  678. }
  679. var size = newPos.length;
  680. var flag = newPos[0]==newPos[size - 1];// 第一个点和最后一个点是否重合,即这些点构成的多边形是否闭合
  681. var dist;
  682. var j = 0;
  683. var hasMinDistPtflag = true;
  684. while (hasMinDistPtflag) {
  685. var hasFlag = false;
  686. for (var i = 0; i < newPos.length - 1; i++) {
  687. if(newPos[i]) {
  688. j = i + 1;
  689. while (!newPos[j] && j < newPos.length){
  690. j ++;
  691. }
  692. if(j==newPos.length){
  693. break;
  694. }
  695. // 判断距离,去除距离很近的后一个点
  696. dist = getDistanceFrom2Pts(newPos[i], newPos[j]);
  697. if (dist < distance) {
  698. if (j == newPos.length - 1) {
  699. delete newPos[i];// 不能去除最后一个点
  700. } else {
  701. delete newPos[j]
  702. }
  703. hasMinDistPtflag = true;
  704. hasFlag = true;
  705. break;
  706. }
  707. }
  708. }
  709. if (!hasFlag) {
  710. hasMinDistPtflag = false;
  711. }
  712. }
  713. if (flag) {
  714. if (newPos.length < 4) {
  715. return null;
  716. }
  717. } else {
  718. if (newPos.length < 2) {
  719. return null;
  720. }
  721. }
  722. var arr=[];
  723. for(var i in newPos){
  724. arr.push(newPos[i]);
  725. }
  726. return arr;
  727. }
  728. /**
  729. * 对一列有序的点根据角度maxAngle去毛刺,尖角,
  730. * @param linePos 有序点集合
  731. * @param maxAngle 角度条件
  732. * @return 平滑去毛刺后的点集
  733. */
  734. function getSmoothPositionFromAngle( linePos, maxAngle) {
  735. if (linePos == null || linePos.length==0) {
  736. //console.log("原始点个数:" + linePos.size());
  737. return null;
  738. }
  739. // System.out.println("原始点个数:" + linePos.size());
  740. var newPos = [];
  741. for(var i in linePos){
  742. newPos[i]=linePos[i];
  743. }
  744. var size = newPos.length;
  745. if (size <= 10) {
  746. return newPos;// 暂定小于等于10个点返回;点太少,处理后形状会改变太大
  747. }
  748. // boolean flag =
  749. // newPos.get(0).equals(newPos.get(size-1));//第一个点和最后一个点是否重合,即这些点构成的多边形是否闭合
  750. var inclination;// 夹角
  751. var j = 0;
  752. var k = 0;
  753. var hasMinAnglePtFlag = true;
  754. while (hasMinAnglePtFlag) {
  755. var hasFlag = false;
  756. for (var i = 1; i < newPos.length - 1; i++) {
  757. if(newPos[i]) {
  758. j = i - 1;
  759. while(!newPos[j]&&j>=0){
  760. j--;
  761. }
  762. k = i + 1;
  763. while(!newPos[k]&&k<newPos.length){
  764. k++
  765. }
  766. if(j<0||k==newPos.length){
  767. break;
  768. }
  769. // 根据角度条件去除毛刺
  770. inclination = getAngleFrom3Pts(newPos[j], newPos[i], newPos[k]);
  771. if (inclination < maxAngle) {
  772. delete newPos[i];
  773. hasMinAnglePtFlag = true;
  774. hasFlag = true;
  775. break;
  776. }
  777. }
  778. }
  779. if (!hasFlag) {
  780. hasMinAnglePtFlag = false;
  781. }
  782. if (newPos.length <= 4) {// 小于四个点直接返回;如果小于4个点还去毛刺,有可能会导致只剩一个点
  783. //console.log("点数小于4个");
  784. break;
  785. }
  786. }
  787. var arr=[];
  788. for(var i in newPos){
  789. arr.push(newPos[i]);
  790. }
  791. return arr;
  792. }
  793. /**
  794. * 算两个点之间的距离
  795. * @param pt1
  796. * @param pt2
  797. * @returns {*}
  798. */
  799. function getDistanceFrom2Pts(p1,p2){
  800. if(p1&&p2) {
  801. return Math.sqrt((p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]));
  802. }else{
  803. //console.log("点数据错误");
  804. return 2000;
  805. }
  806. }
  807. /**
  808. * 三点之间的夹角
  809. * @param p1
  810. * @param p2 夹角所在点
  811. * @param p3
  812. * @return
  813. */
  814. function getAngleFrom3Pts( p1, p2, p3) {
  815. var a2 = (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]);
  816. var c2 = (p1[0] - p3[0]) * (p1[0] - p3[0]) + (p1[1] - p3[1]) * (p1[1] - p3[1]);
  817. var b2 = (p2[0] - p3[0]) * (p2[0] - p3[0]) + (p2[1] - p3[1]) * (p2[1] - p3[1]);
  818. var a = Math.sqrt(a2);
  819. var b = Math.sqrt(b2);
  820. var tmp2ab = 2 * a * b;
  821. var cosC = (a2 + b2 - c2) / tmp2ab;
  822. if(cosC>0.999){
  823. cosC=0.999;
  824. }else if(cosC<-0.999){
  825. cosC=-0.999;
  826. }
  827. return Math.acos(cosC)/Math.PI*180;
  828. }
  829. /**
  830. * 将结果重新组织成二维数组
  831. * @param arr1
  832. * @param arr2
  833. * @returns {Array}
  834. * @private
  835. */
  836. function _formatPoint(arr1,arr2){
  837. var result=[];
  838. for(var i=0;i<arr1.length;i++){
  839. if(arr1[i]&&arr2[i])
  840. result.push([arr1[i],arr2[i]]);
  841. }
  842. return result;
  843. }
  844. return smoothLine;
  845. });