• 用javascript绘制点线数据


    图形学的东西,理论与实际有一定差异,我们实际代码中使用的float,精度会受影响,导致一些算法运算结果与理论有一定差异。而且浮点运算本身就要考虑误差,对误差的大小设置,也影响最终结果呈现。
    最近程序中,有个算法,根据输入的一组点,生成mesh,要求相邻的三个点不能共线,所以需要对这些点做预处理,把共线的点剔除掉。
    写了个算法,很简单,判断三个点是否共线,共线就剔除中间这个点,然后下移一个点,继续判断新的三个点。
    根据各种情况,写了很多测试数据,运行效果也很好,能正常剔除共线点。
    实际运行时,发现有的数据处理后正常,有的数据就离谱了。
    每组点数据多少不一样,几十个到几千个点,打印出来,也很难看出问题。所以要把处理前后的数据做可视化处理。
    代码是C++的,在处理完后,把点数据分别写到两个文件里:

    1. if (origin_points.size()<100)
    2.                     {
    3.                         static int fid = 0;
    4.                         std::string fn  = "D:/ring_" + std::to_string(fid) + ".txt";
    5.                         std::string fn2 = "D:/ring_2_" + std::to_string(fid) + ".txt";
    6.                         
    7.                         recodeData(fn, "origin_points", origin_points);
    8.                         recodeData(fn2, "new_origin_points", new_origin_points);
    9.                         ++fid;
    10.                     }

    判断数据量大小,是为了减少数据输出,先看看比较简单的。
    recodeData使用了boost的json处理类:

    1. #include <fstream>
    2. #include <string>
    3. #include <boost/property_tree/ptree.hpp>
    4. #include <boost/property_tree/json_parser.hpp>
    5. void recodeData(const std::string &fn, const std::string type, const std::vector<glm::vec3> &point_list)
    6. {
    7.     std::ofstream ofs;
    8.     ofs.open(fn, std::ios::out);
    9.     boost::property_tree::ptree root;
    10.     root.put("type", type);
    11.     root.put("count", point_list.size());
    12.     boost::property_tree::ptree json_point_list;
    13.     for (auto &point : point_list)
    14.     {
    15.         boost::property_tree::ptree xy;
    16.         boost::property_tree::ptree x, y;
    17.         x.put("", std::to_string(point.x));
    18.         y.put("", std::to_string(point.y));
    19.         xy.push_back(std::make_pair("", x));
    20.         xy.push_back(std::make_pair("", y));
    21.         json_point_list.push_back(std::make_pair("", xy));
    22.     }
    23.     root.add_child("point_list", json_point_list);
    24.     std::stringstream ss;
    25.     boost::property_tree::write_json(ss, root);
    26.     std::string jsonString = ss.str();
    27.     ofs << jsonString << std::endl;
    28.     ofs.close();
    29. }

    生成的ring_*.txt和ring_2_*.txt是对应的处理前数据和处理后数据,都是json文件,里面的point_list就是点数组,点是二维的,一个点有x、y值组成。
    然后写一个html文件,用于把两个文件读入显示。

    1. <!DOCTYPE html>
    2. <html lang="en">
    3. <head>
    4. <meta charset="UTF-8">
    5. <title>test</title>
    6. <style>
    7. .one,
    8. .two {
    9. width: 50%;
    10. border: 1px solid #ccc;
    11. float: left;
    12. box-sizing: border-box;
    13. }
    14. </style>
    15. </head>
    16. <body>
    17. <div class="one">
    18. <canvas height="720" width="720" id="my_canvas_1"> </canvas>
    19. <br />
    20. <input id="input_1" type="file" name="input_1_file" value="上传文件1" onchange="drawPloyon1(this)" />
    21. </div>
    22. <div class="two">
    23. <canvas height="720" width="720" id="my_canvas_2"> </canvas>
    24. <br />
    25. <input id="input_2" type="file" name="input_2_file" value="上传文件2" onchange="drawPloyon2(this)" />
    26. </div>
    27. </body>
    28. <script>
    29. var canvas_1 = document.getElementById('my_canvas_1');
    30. var canvas_2 = document.getElementById('my_canvas_2');
    31. drawFrame(canvas_1, "red");
    32. drawFrame(canvas_2, "blue");
    33. function drawPoint(ctx, x, y) {
    34. ctx.moveTo(x - 5, y - 5);
    35. ctx.lineTo(x + 5, y - 5);
    36. ctx.lineTo(x + 5, y + 5);
    37. ctx.lineTo(x - 5, y + 5);
    38. ctx.lineTo(x - 5, y - 5);
    39. ctx.lineTo(x + 5, y + 5);
    40. ctx.moveTo(x - 5, y + 5);
    41. ctx.lineTo(x + 5, y - 5);
    42. ctx.moveTo(x, y);
    43. }
    44. function drawFrame(mycanvas, color) {
    45. var w = mycanvas.width;
    46. var h = mycanvas.height;
    47. var ctx = mycanvas.getContext('2d');
    48. ctx.strokeStyle = color;
    49. ctx.beginPath();
    50. ctx.moveTo(0, 0);
    51. ctx.lineTo(w - 1, 0);
    52. ctx.lineTo(w - 1, h - 1);
    53. ctx.lineTo(0, h - 1);
    54. ctx.lineTo(0, 0);
    55. ctx.closePath();
    56. ctx.stroke();
    57. }
    58. function drawLine(json_str, my_canvas) {
    59. var ctx = my_canvas.getContext('2d');
    60. ctx.strokeStyle = "green";
    61. ctx.beginPath();
    62. var x0, y0;
    63. var obj_json = JSON.parse(json_str);
    64. var point_list = obj_json.point_list;
    65. var x_max = -Number.MAX_VALUE;
    66. var x_min = Number.MAX_VALUE;
    67. var y_max = -Number.MAX_VALUE;
    68. var y_min = Number.MAX_VALUE;
    69. for (var i = 0; i < point_list.length; i++) {
    70. var xy = point_list[i];
    71. var x = Number(xy[0]);
    72. var y = Number(xy[1]);
    73. if (x_min > x) x_min = x;
    74. if (x_max < x) x_max = x;
    75. if (y_min > y) y_min = y;
    76. if (y_max < y) y_max = y;
    77. }
    78. var x_len = x_max - x_min;
    79. var y_len = y_max - y_min;
    80. var ppl;
    81. if (x_len > y_len) {
    82. ppl = my_canvas.width / x_len;
    83. }
    84. else {
    85. ppl = my_canvas.height / y_len;
    86. }
    87. for (var i = 0; i < point_list.length; i++) {
    88. var xy = point_list[i];
    89. var x = Number(xy[0]);
    90. var y = Number(xy[1]);
    91. console.log("x:" + x + ",y:" + y);
    92. x = (x - x_min) * ppl;
    93. y = (y - y_min) * ppl;
    94. if (i != 0)
    95. ctx.lineTo(x, y);
    96. else {
    97. x0 = x;
    98. y0 = y;
    99. ctx.moveTo(x, y);
    100. }
    101. ctx.stroke();
    102. drawPoint(ctx, x, y);
    103. }
    104. //ctx.lineTo(x0, y0);
    105. ctx.moveTo(x0, y0);
    106. ctx.lineTo(x0 + 10, y0);
    107. ctx.lineTo(x0 - 10, y0);
    108. ctx.lineTo(x0, y0);
    109. ctx.lineTo(x0, y0 + 10);
    110. ctx.lineTo(x0, y0 - 10);
    111. ctx.closePath();
    112. ctx.stroke();
    113. }
    114. function drawPloyon1(source) {
    115. var input = source;
    116. var reader = new FileReader();
    117. reader.readAsText(input.files[0]);
    118. reader.onload = function () {
    119. if (reader.result) {
    120. //显示文件内容
    121. temp_str = reader.result;
    122. var w = canvas_1.width;
    123. var h = canvas_1.height;
    124. canvas_1.getContext('2d').clearRect(0, 0, w, h);
    125. drawLine(temp_str, canvas_1);
    126. }
    127. };
    128. }
    129. function drawPloyon2(source) {
    130. var input = source;
    131. var reader = new FileReader();
    132. reader.readAsText(input.files[0]);
    133. reader.onload = function () {
    134. if (reader.result) {
    135. //显示文件内容
    136. temp_str = reader.result;
    137. var w = canvas_2.width;
    138. var h = canvas_2.height;
    139. canvas_2.getContext('2d').clearRect(0, 0, w, h);
    140. drawLine(temp_str, canvas_2);
    141. }
    142. };
    143. }
    144. </script>
    145. </html>

    运行后:

    通过对比,找到比较离谱的数据,再去分析改进算法。
    可以看到javascript还是很方便的,一百多行就可以读取文件绘制曲线。

  • 相关阅读:
    学生个人网页模板 学生个人网页设计作品 简单个人主页成品 个人网页制作 HTML学生个人网站作业设计代做
    【金融项目】尚融宝项目(十五)
    前端try和catch
    OpenHarmony SystemUI开发记录
    2.2 在 Linux 上安装 MySQL Shell
    教你几招,轻松实现视频转音频
    【Linux】Linux终端执行docker内部shell脚本
    淘宝/天猫获得淘宝商品详情(关键词搜索,店铺所有商品)API接口返回值说明
    Spring Cloud Tencent 迎来 1.7.0 大版本更新,欢迎体验
    Notes中的进度条
  • 原文地址:https://blog.csdn.net/caz28/article/details/125519156