Polyline Simplification (计算几何)

本文介绍了一种Polyline简化算法,该算法通过逐步移除多边线路线中面积最小的三角形来减少线段数量,最终达到减少细节并提高处理效率的目的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Polyline Simplification

时间限制: 5 Sec   内存限制: 128 MB
提交: 35   解决: 11
[ 提交][ 状态][ 讨论版][命题人: admin]

题目描述

Mapping applications often represent the boundaries of countries, cities, etc. as polylines, which are connected sequences of line segments. Since fine details have to be shown when the user zooms into the map,these polylines often contain a very large number of segments. When the user zooms out, however, these fine details are not important and it is wasteful to process and draw the polylines with so many segments. In this problem, we consider a particular polyline simplification algorithm designed to approximate the original polyline with a polyline with fewer segments.
A polyline with n segments is described by n + 1 points p0 = (x0, y0),... , pn = (xn, yn), with the ith line segment being  . The polyline can be simplified by removing an interior point pi (1≤i≤n-1),so that the line segments  are replaced by the line segment . To select the point to be removed, we examine the area of the triangle formed by pi-1, pi, and pi+1 (the area is 0 if the three points are colinear), and choose the point pi such that the area of the triangle is smallest. Ties are broken by choosing the point with the lowest index. This can be applied again to the resulting polyline, until the desired number m of line segments is reached. 
Consider the example below.
The original polyline is shown at the top. The area of the triangle formed by p2, p3, and p4 is considered (middle), and p3 is removed if the area is the smallest among all such triangles. The resulting polyline after p3 is removed is shown at the bottom.

输入

The first line of input contains two integers n (2≤n≤200 000) and m (1≤m < n). The next n+1 lines specify p0,..., pn. Each point is given by its x and y coordinates which are integers between -5000 and 5000 inclusive. You may assume that the given points are strictly increasing in lexicographical order. That is, xi < xi+1, or x= xi+1 and yi < yi+1 for all 0≤i < n.

输出

Print on the kth line the index of the point removed in the kth step of the algorithm described above (use the index in the original polyline).

样例输入

10 7

0 0

1 10

2 20

25 17

32 19

33 5

40 10

50 13
65 27

75 22

85 17

样例输出

1
9
6

简单的题意,简单的思路,debug一天,就是这么简单。
题意是 有n条边,n+1个点,由点Pi-1,Pi,Pi+1组成的若干个三角形,每次删除面积最小的三角形的中间点,最后剩下m条边,问每次删除的点是哪些。

首先,很容易想到把所有的点压入优先队列,每一次取最小的点,但是去除一个点之后可能会产生两个新的三角形,这样需要两个数组来记录前驱和后继,然后新的问题出现,不只是加入了两个新点,还会影响到另外的两个三角形,而且这两个三角形要直接pop掉,所以再在结构体里面加两个标记位,来记录前驱后继是否相同,不相同就pop掉,最后得到结果。

代码实现:
#include<bits/stdc++.h>
#define ll long long
using namespace std;

const int N = 2e5+10;
int n,m;
int pre[N],nxt[N];
struct Point{
    double x,y;
    Point(double x=0, double y =0):x(x),y(y){}
}p[N];
int vis[N];
struct Area{
    double area;
    int indx,l,r;
    Area (int l,int mid,int r,double area):l(l),indx(mid),r(r),area(area){};
    friend bool operator < (Area A, Area B){
    	if(A.area==B.area)
    	return A.indx>B.indx;
        return  A.area > B.area;
    }
};
priority_queue<Area>pq;
typedef Point Vector;

Vector operator - (Vector A, Vector B){
    return Vector(A.x-B.x,A.y-B.y);
}

double Cross(Vector A, Vector B){
    return A.x*B.y-A.y*B.x;
}

double Area2(Point A, Point B, Point C){
    return Cross(B-A,C-A);
}
vector <int> ans;
int main()
{
    int i,j,k;
    scanf("%d%d",&n,&m);
    for(i = 1; i <= n+1; i ++) 
	scanf("%lf%lf",&p[i].x,&p[i].y);
    for(i=1;i<=n+1;i++)
    {
        pre[i]=i-1;
        nxt[i]=i+1;
    }
    nxt[0]=1;
    for(i = 2; i <= n; i ++)
	{
    	double s=fabs(Area2(p[i-1],p[i],p[i+1]));
        Area area1(i-1,i,i+1,s);
        pq.push(area1);
    }
    
    int t=n-m;
    while(t)
    {
        Area tt=pq.top();
        pq.pop();
        if(vis[tt.indx]||tt.l!=pre[tt.indx]||tt.r!=nxt[tt.indx])
		continue;
		t--;
        vis[tt.indx]=1;
        i=tt.indx;
        pre[nxt[i]]=pre[i];
        nxt[pre[i]]=nxt[i];
        ans.push_back(i);
        int temp=pre[tt.indx];
        if(temp>1)
		pq.push(Area{pre[temp],temp,nxt[temp],fabs(Area2(p[temp],p[pre[temp]],p[nxt[temp]]))});
		temp=nxt[tt.indx];
        if(temp<=n)
		pq.push(Area{pre[temp],temp,nxt[temp],fabs(Area2(p[temp],p[pre[temp]],p[nxt[temp]]))});
    }
    for(i=0;i<ans.size();i++)
    {
        printf("%d\n",ans[i]-1);
    }
    return 0;
}
/*
10 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
*/

### 如何在 Cesium 中计算 Polyline 的质心 在 Cesium 中,`Polyline` 是一种用于绘制三维场景中的折线的实体。要计算 `Polyline` 的质心(centroid),可以采用几何方法来处理其顶点坐标集合。以下是实现这一目标的具体方式: #### 方法概述 1. **提取 Polyline 的顶点数据** 需要获取构成该多边形的所有顶点位置。这些顶点通常存储在一个数组中,可以通过设置或读取 `positions` 属性获得。 2. **转换为笛卡尔坐标系下的向量** 使用 Cesium 提供的方法将地理坐标 (经纬度) 转换到笛卡尔空间中的三维向量形式。这一步骤对于后续计算至关重要[^1]。 3. **应用加权平均法求解质心** 对于每一对连续点之间的距离权重,通过累加它们的位置矢量并除以总数量得到最终的结果。 下面是具体的代码示例: ```javascript function calculateCentroid(positions, ellipsoid = Cesium.Ellipsoid.WGS84) { const cartesians = []; // 将地理位置转成笛卡尔坐标 for (let i = 0; i < positions.length; ++i) { const cartesian = Cesium.Cartesian3.fromDegrees( positions[i].longitude, positions[i].latitude, positions[i].height || 0, ellipsoid ); cartesians.push(cartesian); } let sumX = 0; let sumY = 0; let sumZ = 0; // 计算所有点坐标的均值作为近似中心 for (const point of cartesians) { sumX += point.x; sumY += point.y; sumZ += point.z; } const count = cartesians.length; const centroidCartesian = new Cesium.Cartesian3(sumX / count, sumY / count, sumZ / count); // 如果需要返回纬度/经度,则反变换回地理坐标 const centroidGeoPosition = Cesium.Cartographic.fromCartesian(centroidCartesian, ellipsoid); return { longitude: Cesium.Math.toDegrees(centroidGeoPosition.longitude), latitude: Cesium.Math.toDegrees(centroidGeoPosition.latitude), height: centroidGeoPosition.height }; } // 示例调用 const polylinePositions = [ { longitude: -75.5986, latitude: 40.039 }, { longitude: -117.1872, latitude: 32.7189 }, { longitude: -118.2437, latitude: 34.0522 } ]; const centroid = calculateCentroid(polylinePositions); console.log(`Centroid is at Longitude=${centroid.longitude}, Latitude=${centroid.latitude}`); ``` 上述函数实现了从一组给定的经纬度输入到输出对应质心的过程。注意这里假设高度默认为零;如果实际模型中有不同海拔高度的数据也应考虑进去调整算法逻辑。 --- ### 注意事项 - 当前实现基于简单的算术平均值估算质心位置,在某些情况下可能不够精确特别是当路径跨越较大范围或者接近极地区域时。 - 更复杂的解决方案涉及积分运算以及更精细地考虑到地球曲率影响等因素,但这超出了基本需求范畴并且增加了编程难度。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值