从坐标图中绘制多边形画布

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了从坐标图中绘制多边形画布相关的知识,希望对你有一定的参考价值。

如何将坐标图转换为点画布?

我有一张地图传单Map leaflet,当我选择多边形时,我想用画布html5绘制多边形

我有这样的坐标:

[[2.809510437833253,49.408625488749216],[2.8095461924850422,49.40864172401838],[2.8095226856172806,49.40866595550704],[2.809565304449213,49.40868849340382],[2.8097185865450465,49.40858536874469],[2.809677338568488,49.40856463072128],[2.8096442193374154,49.408580757620854],[2.809609885351463,49.40855283978645],[2.809510437833253,49.408625488749216]]

困难在于如何从地图坐标获取点

此示例显示多边形画布:

<!DOCTYPE html>
<html>
<body>
<svg height="110" width="200">
<polygon points="130,0 0,160 0,485 270,645 560,485 560,160"/>
</svg>
</body>
</html>

谢谢你的帮助。

答案

地图投影

Difficult problem

地球的问题是不是平坦的,我们人类用来绘制和渲染的大多数都是平坦的。为了解决这个问题,我们通过应用从圆形地球到平面地图的投影来接受地图所代表的变形。有许多不同类型的投影,常见的是墨卡托投影(参见谷歌地图),它会扭曲你赤道南部和北部的区域。但这样做是为了保持方向。您可以将指南针放在墨卡托投影地图上并获得准确的方位,但是您不能用尺子测量距离。

But size matters, easy solution

但是这一切都有一个拯救的恩典。我们人类与地球相比很小,而对于局部地图,由地球曲率引起的失真是如此之小以至于无关紧要。

如果您在一个小区域(例如城市和郊区)中有一组坐标,则可以使用方形投影。 lat和long在渲染表面的网格上是x和y。

Step by step

如何获取一些映射数据并将其适合保持方面的画布。

所以你有一组点和画布上下文

<canvas id="canvas" width =300 height = 200></canvas>
ctx = canvas.getContext("2d");

 var myPoints = [[2.809510437833253,49.408625488749216],[2.8095461924850422,49.40864172401838],[2.8095226856172806,49.40866595550704],[2.809565304449213,49.40868849340382],[2.8097185865450465,49.40858536874469],[2.809677338568488,49.40856463072128],[2.8096442193374154,49.408580757620854],[2.809609885351463,49.40855283978645],[2.809510437833253,49.408625488749216]]

然后找到那些点的范围(最小和最大坐标)

var minX,minY,maxX,maxY; 
myPoints.forEach((p,i) => {
   if(i === 0){ // if first point 
      minX = maxX = p[0];
      minY = maxY = p[1]; 
   }else{
      minX = Math.min(p[0],minX);
      minY = Math.min(p[1],minY);
      maxX = Math.max(p[0],maxX);
      maxY = Math.max(p[1],maxY);
   }
 });
 // now get the map width and heigth in its local coords
 const mapWidth = maxX-minX;
 const mapHeight = maxY-minY;
 const mapCenterX = (maxX + minX) /2;
 const mapCenterY = (maxY + minY) /2;

现在您有了地图范围,您可以通过找到适合宽度和高度的最小比例来将其缩放到画布。

 const scale = Math.min(canvas.width / mapWidth,canvas.height / mapHeight);

现在,您可以先绘制地图中心,然后将其缩放,然后移动到画布中心。

 ctx.beginPath();
 myPoints.forEach(p => { 
      ctx.lineTo(
          (p[0] - mapCenterX) * scale + canvas.width /2 ,
          (p[1] - mapCenterY) * scale + canvas.height / 2 
      );
 });
 ctx.stroke();

And a working example.

 ctx = canvas.getContext("2d");
 
 var myPoints = [[2.809510437833253,49.408625488749216],[2.8095461924850422,49.40864172401838],[2.8095226856172806,49.40866595550704],[2.809565304449213,49.40868849340382],[2.8097185865450465,49.40858536874469],[2.809677338568488,49.40856463072128],[2.8096442193374154,49.408580757620854],[2.809609885351463,49.40855283978645],[2.809510437833253,49.408625488749216]]

var minX,minY,maxX,maxY; 
myPoints.forEach((p,i) => {
   if(i === 0){ // if first point 
      minX = maxX = p[0];
      minY = maxY = p[1]; 
   }else{
      minX = Math.min(p[0],minX);
      minY = Math.min(p[1],minY);
      maxX = Math.max(p[0],maxX);
      maxY = Math.max(p[1],maxY);
   }
 });
 // now get the map width and heigth in its local coords
 const mapWidth = maxX-minX;
 const mapHeight = maxY-minY;
 const mapCenterX = (maxX + minX) /2;
 const mapCenterY = (maxY + minY) /2;
 
 // to find the scale that will fit the canvas get the min scale to fit height or width
 const scale = Math.min(canvas.width / mapWidth,canvas.height / mapHeight);
 
 // Now you can draw the map centered on the cavas
 ctx.beginPath();
 myPoints.forEach(p => { 
      ctx.lineTo(
          (p[0] - mapCenterX) * scale + canvas.width /2 ,
          (p[1] - mapCenterY) * scale + canvas.height / 2 
      );
 });
 ctx.stroke();
canvas { border : 2px solid black; }
<canvas id="canvas" width =300 height = 200></canvas>

以上是关于从坐标图中绘制多边形画布的主要内容,如果未能解决你的问题,请参考以下文章

不从坐标(从数组)在地图上绘制多边形

使用 html5 画布将图像剪辑成多边形的可重用函数

画布,负坐标:绘制从画布开始并继续下去的路径是不是不好?

D3.js:坐标轴

通过鼠标使用 PyQwt 从画布上记录曲线/多边形

React 绘制图形