如何计算贝塞尔曲线的面积?

2024-03-19

给定以下描述 SVG 三次贝塞尔曲线的路径(例如):

M 300,140 C 300,40, 500,40, 500,140

并假设有一条直线连接端点300,140 to 500,140(封闭曲线下的面积),是否可以计算如此封闭的面积?

谁能建议一个公式(或 JavaScript)来完成这个任务?


将路径转换为多边形 http://phrogz.net/svg/convert_path_to_polygon.xhtml任意精度,然后计算多边形的面积 http://www.wikihow.com/Calculate-the-Area-of-a-Polygon.

Interactive Demo: Area of Path via Subdivision http://phrogz.net/svg/area_of_path_via_subdivision.xhtml (broken)

                      Screenshot of Demo

上面的演示的核心是使用函数自适应地将路径细分为多边形 http://phrogz.net/svg/libraries/SVGPathToPolyViaSubDivision.js and 计算多边形的面积 http://phrogz.net/svg/libraries/SVGPolyArea.js:

// path:      an SVG <path> element
// threshold: a 'close-enough' limit (ignore subdivisions with area less than this)
// segments:  (optional) how many segments to subdivisions to create at each level
// returns:   a new SVG <polygon> element
function pathToPolygonViaSubdivision(path,threshold,segments){
  if (!threshold) threshold = 0.0001; // Get really, really close
  if (!segments)  segments = 3;       // 2 segments creates 0-area triangles

  var points = subdivide( ptWithLength(0), ptWithLength( path.getTotalLength() ) );
  for (var i=points.length;i--;) points[i] = [points[i].x,points[i].y];

  var doc  = path.ownerDocument;
  var poly = doc.createElementNS('http://www.w3.org/2000/svg','polygon');
  poly.setAttribute('points',points.join(' '));
  return poly;

  // Record the distance along the path with the point for later reference
  function ptWithLength(d) {
    var pt = path.getPointAtLength(d); pt.d = d; return pt;
  }

  // Create segments evenly spaced between two points on the path.
  // If the area of the result is less than the threshold return the endpoints.
  // Otherwise, keep the intermediary points and subdivide each consecutive pair.
  function subdivide(p1,p2){
    var pts=[p1];
    for (var i=1,step=(p2.d-p1.d)/segments;i<segments;i++){
      pts[i] = ptWithLength(p1.d + step*i);
    }
    pts.push(p2);
    if (polyArea(pts)<=threshold) return [p1,p2];
    else {
      var result = [];
      for (var i=1;i<pts.length;++i){
        var mids = subdivide(pts[i-1], pts[i]);
        mids.pop(); // We'll get the last point as the start of the next pair
        result = result.concat(mids)
      }
      result.push(p2);
      return result;
    }
  }

  // Calculate the area of an polygon represented by an array of points
  function polyArea(points){
    var p1,p2;
    for(var area=0,len=points.length,i=0;i<len;++i){
      p1 = points[i];
      p2 = points[(i-1+len)%len]; // Previous point, with wraparound
      area += (p2.x+p1.x) * (p2.y-p1.y);
    }
    return Math.abs(area/2);
  }
}
// Return the area for an SVG <polygon> or <polyline>
// Self-crossing polys reduce the effective 'area'
function polyArea(poly){
  var area=0,pts=poly.points,len=pts.numberOfItems;
  for(var i=0;i<len;++i){
    var p1 = pts.getItem(i), p2=pts.getItem((i+-1+len)%len);
    area += (p2.x+p1.x) * (p2.y-p1.y);
  }
  return Math.abs(area/2);
}

以下是原始答案,它使用不同的(非自适应)技术来转换<path> to a <polygon>.

Interactive Demo: http://phrogz.net/svg/area_of_path.xhtml http://phrogz.net/svg/area_of_path.xhtml (broken)

                  Screenshot of Demo

上面的演示的核心是使用函数用多边形逼近路径 http://phrogz.net/svg/libraries/SVGPathToPoly.js and 计算多边形的面积 http://phrogz.net/svg/libraries/SVGPolyArea.js.

// Calculate the area of an SVG polygon/polyline
function polyArea(poly){
  var area=0,pts=poly.points,len=pts.numberOfItems;
  for(var i=0;i<len;++i){
    var p1 = pts.getItem(i), p2=pts.getItem((i+len-1)%len);
    area += (p2.x+p1.x) * (p2.y-p1.y);
  }
  return Math.abs(area/2);
}

// Create a <polygon> approximation for an SVG <path>
function pathToPolygon(path,samples){
  if (!samples) samples = 0;
  var doc = path.ownerDocument;
  var poly = doc.createElementNS('http://www.w3.org/2000/svg','polygon');

  // Put all path segments in a queue
  for (var segs=[],s=path.pathSegList,i=s.numberOfItems-1;i>=0;--i)
    segs[i] = s.getItem(i);
  var segments = segs.concat();

  var seg,lastSeg,points=[],x,y;
  var addSegmentPoint = function(s){
    if (s.pathSegType == SVGPathSeg.PATHSEG_CLOSEPATH){
      
    }else{
      if (s.pathSegType%2==1 && s.pathSegType>1){
        x+=s.x; y+=s.y;
      }else{
        x=s.x; y=s.y;
      }          
      var last = points[points.length-1];
      if (!last || x!=last[0] || y!=last[1]) points.push([x,y]);
    }
  };
  for (var d=0,len=path.getTotalLength(),step=len/samples;d<=len;d+=step){
    var seg = segments[path.getPathSegAtLength(d)];
    var pt  = path.getPointAtLength(d);
    if (seg != lastSeg){
      lastSeg = seg;
      while (segs.length && segs[0]!=seg) addSegmentPoint( segs.shift() );
    }
    var last = points[points.length-1];
    if (!last || pt.x!=last[0] || pt.y!=last[1]) points.push([pt.x,pt.y]);
  }
  for (var i=0,len=segs.length;i<len;++i) addSegmentPoint(segs[i]);
  for (var i=0,len=points.length;i<len;++i) points[i] = points[i].join(',');
  poly.setAttribute('points',points.join(' '));
  return poly;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何计算贝塞尔曲线的面积? 的相关文章

随机推荐

  • PRG 模式是否有一个在验证失败时不会重定向的名称?

    我的网站遵循重定向后获取模式 似乎有两种方法可以处理失败的验证 任何一个 使用验证消息渲染页面 临时存储验证消息 并重定向到显示消息的 GET 这两种实现都遵循 PRG 模式吗 是否有更具体的方法来描述这两种模式 我问这个问题主要是为了教育
  • 文件 ld-linux-x86-64.so.2 中未定义版本 GLIBC_PRIVATE

    如果有人可以给初学者一些有关 gcc 版本问题的帮助吗 我遇到了这个问题 version GLIBCXX 3 4 20 not found 我点击链接后 如何在 CentOS 7 2 上使用 yum 安装 gcc 5 3 https sta
  • 静态变量顺序[重复]

    这个问题在这里已经有答案了 我对 C 中静态变量声明的顺序有疑问 当我运行这段代码时 static class Program private static int v1 15 private static int v2 v1 static
  • 具有虚函数的类的大小

    我正在修改 C 概念 但我坚持使用非常简单的代码 include
  • Dart 产生来自另一个流监听器的流事件

    我有一个函数可以生成stream的具体事件 现在我有一个来自存储服务的流 它有自己的事件 寻找一种方法在发生变化时产生我的事件storage stream 这段代码片段并不能解决问题 Stream
  • 输入空值时停止提交

    我正在寻找一个简单的解决方案来阻止登录表单提交空输入字段 表格的代码如下 如果可能的话 我想使用一个简单的 Javascript 解决方案
  • 如果模式匹配,则打印 lua 表中的值

    好吧 我最近刚接触 lua 发现自己陷入了以下困境 我有函数peripheral getNames 这是一个自定义函数 它将返回一个具有结构 key value 的表 而 key 始终是一个数字 从 1 开始 value 将是该函数找到的内
  • 在区域注册中注册路线

    我所在区域有两条路线 一条是自定义路线 一条是默认后备路线 请参见下文 var dashboardRoute new DashboardRoute ObjectFactory GetInstance
  • 为什么intellij IDEA高亮显示build.sbt?

    我最近在 IDEA 中使用 sbt 创建了一个新项目并得到了这个 它出什么问题了 我安装并启用了 scala 插件 IDEA 版本是 14 好的 我找到了解决这个问题的方法 链接在这里 https stackoverflow com a 2
  • DataSource 和 ConnectionPoolDataSource 之间的区别

    有什么区别javax sql DataSource http docs oracle com javase 6 docs api javax sql DataSource html and javax sql ConnectionPoolD
  • 在 Angular2 的自定义验证器中注入服务

    我尝试使用自定义验证器中的服务来检查用户名是否已存在 import Component from angular2 core import Control ControlGroup FormBuilder from angular2 com
  • 如何从旋转矩阵计算角度

    我使用单个对象的两个图像 该对象从第一个图像旋转一定角度 我计算了每个图像的姿势 并使用 Rodergues 将旋转向量转换为矩阵 现在我如何计算并查看它从第一个位置旋转了多少 我尝试了很多方法 但答案是否定的 编辑 我的相机是固定的 只有
  • 无法解析 fromJson

    我看过了这个线程 https stackoverflow com questions 17453406 gson with mixed read and 这个线程 https stackoverflow com questions 3231
  • CodeIgniter 1.7 升级到 2.1 后出现未定义的 $load 属性错误

    为什么在将 CodeIgniter 从 v1 7 升级到 v2 1 后出现此错误 A PHP Error was encountered Severity Notice Message Undefined property Site loa
  • 在 uwsgi 下运行的单元测试 Flask 应用程序

    我对 python 比较陌生 正在寻找一种 pythonic 方法来处理这种实践 我继承了一个相当简单的 Python 2 7 Flask 应用程序 该应用程序在 uwsgi 下运行 我想向其中添加一些单元测试 它在缩进级别 0 上进行一些
  • SQL FOR XML 路径列表和计数

    我有一张表 例如 Date Name 20 May 2011 Bob 20 May 2011 Fred 20 May 2011 Jim 21 May 2011 Bob 21 May 2011 Ed 22 May 2011 Bill 我需要一
  • 如何检查 ASP.NET 4 是否注册为在 IIS 7.5 中运行?

    如何检查 ASP NET 4 是否注册为在 IIS 7 5 中运行 除了运行之外 必须有某种方法可以确定这一点 aspnet regiis i 从框架的文件夹内 我不需要以编程方式检查这一点 只需通过 IIS 管理器或命令行即可 我有一个
  • setFirstResult 和 setMaxResult 与 Order By 配合使用效果不佳

    什么可能导致CriteriaQuery orderBy方法停止工作 以下是具体实现 OpenJPAEntityManager kem OpenJPAPersistence cast entityManager kem getFetchPla
  • 将 JSON 字符串转换为 JAVA 中的通用对象(使用 GSON)

    我有一个返回 JSON 的 Api 响应采用某种格式 可以放入名为 ApiResult 的对象中 并包含Context
  • 如何计算贝塞尔曲线的面积?

    给定以下描述 SVG 三次贝塞尔曲线的路径 例如 M 300 140 C 300 40 500 40 500 140 并假设有一条直线连接端点300 140 to 500 140 封闭曲线下的面积 是否可以计算如此封闭的面积 谁能建议一个公