点密度专题图个人理解,某区域内某个属性值得大小以点的个数显示。
步骤:
1.查询获取属性值;
2.设置单点值大小,计算点个数
3.随机生成点;
4.将点显示到graphiclayer图层;
这里的主要难点是如何在区域(以下称多边形)内生成指定个数的点;本人的主要思路是:
1.获取区域的范围和多边形顶点;
2.利用随机函数生成范围内的随机点;
3.判断点是否在多边形内;
4.将在多边形内的点记录,达到指定个数,结束;
其中,判断点在任意多边形内的方法,是以随机点为起点,像左过范围做一条线段,若该线段,与多边形的交点个数为偶数则在多边形外,奇数为内,
算法如下:
/// <summary>
/// 获取任意多边形中指定个数的随机点
/// </summary>
/// <param name="polygon">多边形</param>
/// <param name="count">生成随机点的个数</param>
/// <returns></returns>
public static List<MapPoint> CalRandomPoints(ESRI.ArcGIS.Client.Geometry.Polygon polygon, int count)
{
List<MapPoint> listMp = new List<MapPoint>();
if (polygon == null || count <= 0) return listMp;
if (count == 1)
CalOnePoint(polygon);
Envelope initEnvelope = polygon.Extent;
System.Random rd = new Random();//随机数
double rd1 = 0, rd2 = 0; int sum = 0;
bool isIn = false;
double extentWidth = initEnvelope.XMax - initEnvelope.XMin;
double extentHeight = initEnvelope.YMax - initEnvelope.YMin;
while (sum != count)
{
rd1 = rd.NextDouble();
rd2 = rd.NextDouble();
double tmpX = initEnvelope.XMin + rd1 * extentWidth;
double tmpY = initEnvelope.YMin + rd2 * extentHeight;
MapPoint newPoint = new MapPoint(tmpX, tmpY);
isIn = isInPolygon(polygon, newPoint);
if (isIn)
{
listMp.Add(newPoint);
sum++;
}
}
return listMp;
}
/// <summary>
/// 判断点是否在多边形内
/// </summary>
/// <returns></returns>
private static bool isInPolygon(ESRI.ArcGIS.Client.Geometry.Polygon polygon,MapPoint mpoint)
{
bool _isIN = true;
System.Random rd = new Random();
MapPoint endPoint = new MapPoint();
endPoint.Y = mpoint.Y;
endPoint.X = polygon.Extent.XMin-100000;
ILineSegment ls2 = new ILineSegment();
ls2.StartPoint = mpoint;
ls2.EndPoint = endPoint;
System.Collections.ObjectModel.ObservableCollection<ESRI.ArcGIS.Client.Geometry.PointCollection> pc =
polygon.Rings;
ESRI.ArcGIS.Client.Geometry.PointCollection tmpPc;
MapPoint tmpSMP,tmpEMP;
ILineSegment ls1;
int crossSum=0;
for (int i = 0; i < pc.Count; i++)
{
tmpPc = pc[i];
for (int j = 0; j < tmpPc.Count-1; j++)//顺时针,负为正
{
tmpSMP = tmpPc[j]; tmpEMP = tmpPc[j + 1];
ls1 = new ILineSegment();
ls1.StartPoint = tmpSMP; ls1.EndPoint = tmpEMP;
if (ls1 == null || ls2 == null) continue;
bool iscross = isSegmentCrossing(ls1, ls2);
bool lsl1l2 = isSegmentCrossing(ls2, ls1);//l1是否穿过l2
if (iscross&&lsl1l2)
crossSum++;
}
}
if (crossSum % 2 == 0)//偶数在多边形外
_isIN = false;
else
_isIN = true;
return _isIN;
}
/// <summary>
/// 判断两线段是否相交是否相交
/// </summary>
/// <param name="ls1"></param>
/// <param name="ls2"></param>
/// <returns></returns>
private static bool isSegmentCrossing(ILineSegment ls1, ILineSegment ls2)
{
bool iscross = false;
//l2--l1
double cj1 = calPointLoaction(ls2.StartPoint, ls1);
double cj2 = calPointLoaction(ls2.EndPoint, ls1);
if (cj1 > 0 && cj2 > 0)
iscross = false;
else if (cj1 < 0 && cj2 < 0)
iscross = false;
else
iscross = true;
return iscross;
}
/// <summary>
/// 计算一个点在线段的左右
/// </summary>
/// <param name="point"></param>
/// <param name="line"></param>
/// <returns></returns>
private static double calPointLoaction(MapPoint point, ILineSegment line)
{
double cj = 0;
double ax = line.StartPoint.X - point.X;
double ay = line.StartPoint.Y - point.Y;
double bx = line.EndPoint.X - point.X;
double by = line.EndPoint.Y - point.Y;
cj = ax * by - bx * ay;
return cj;
}
效果图如下(貌似还可以呵呵):