天天看点

关于OpenRs矢量选择矢量数据时出现异常的修改。矢量选择错误情况概述错误修改

关于OpenRS矢量选择错误的修改

  • 矢量选择错误情况概述
    • OpenRS问题概述
  • 错误修改

矢量选择错误情况概述

在对OpenRS进行,矢量数据处理的测试时,发现的问题。以OpenRS中矢量图层中移动顶点功能为例,如下图菜单所示。

关于OpenRs矢量选择矢量数据时出现异常的修改。矢量选择错误情况概述错误修改

在矢量的一级菜单下面有着移动顶点,插入顶点,删除单个顶点以及删除框选顶点等功能操作。

在进行这些操作中都需要选中待处理的目标矢量,如下图所示:在1位置处的红色矢量未被选中,在2位置处的矢量为选中状态。

关于OpenRs矢量选择矢量数据时出现异常的修改。矢量选择错误情况概述错误修改

OpenRS问题概述

****OpenRs中如果有一条矢量,其max_y,max_x,min_x,min_y中构成的一个矩形框。只要鼠标在矩形框的范围中点击,将会无条件选中该矢量,如果多条矢量的矩形框重合,则选择先检索到的矢量。

当某一条矢量所形成的矩形框足够大,则无论点击何处位置也无法取消选中状态。

为解决该问题,首先对选择算法进行更改,首先根据鼠标点击获得一个初始点,求取初始点与矢量的每一个节点的距离,选取里矢量最近的两个点,

****1)先判断这两个点和初始点的距离是否小于4,如果小于4则认为要选中该条矢量,如果大于4,进入第2)过程。

****2)求两点构成的线段函数,求取初始点到线段的距离,如果距离小于4则认为选中,如果大于4认为该初始点,处没有选择的矢量。具体增加的函数如下所示。

错误修改

orsXSFLayer.cpp

bool orsXSFLayer::PickFeature(const orsPOINT3D &point3D, double snapRadius )
{
	if( !IsVisible() || NULL == m_osfLayer.get() )
		return false;
	
	double dMaxx,dMinx,dMaxy,dMiny;
	dMaxx = point3D.X + snapRadius / 2;
	dMinx = point3D.X - snapRadius / 2;
	dMaxy = point3D.Y + snapRadius / 2;
	dMiny = point3D.Y - snapRadius / 2;
	
	ref_ptr<osfIPolygon> pPolygon = getSFService()->createPolygon();
	if (NULL == pPolygon.get())
	{
		return false;
	}

	ref_ptr<osfILinearRing> pLinearRing = getSFService()->createLinearRing();
	if (NULL == pLinearRing.get())
	{
		return false;
	}
	
	//construct polygon
	pLinearRing->setNumPoints(4);
	orsPOINT3D point;
	point.X = dMaxx;	point.Y = dMaxy;point.Z = 0.0;
	pLinearRing->setPoint(0,point);
	point.X = dMaxx;	point.Y = dMiny;point.Z = 0.0;
	pLinearRing->setPoint(1,point);
	point.X = dMinx;	point.Y = dMiny;point.Z = 0.0;
	pLinearRing->setPoint(2,point);
	point.X = dMinx;	point.Y = dMaxy;point.Z = 0.0;
	pLinearRing->setPoint(3,point);
	point.X = dMaxx;	point.Y = dMaxy;point.Z = 0.0;
	pLinearRing->setPoint(4,point);
	pPolygon->addRing(pLinearRing.get());
	
	m_osfLayer->SetSpatialFilter(pPolygon.get());
	
	//注意,用filter后,就不能快速获取feature数目了。
	m_osfLayer->ResetReading();
	
	osfIFeature *poFeature = NULL;

	while( (poFeature = m_osfLayer->GetNextFeature()) != NULL )
	{
		if( !IsDeleted( poFeature ) ) 
		{
			m_pPickedFeature = poFeature;
			m_osfLayer->SetSpatialFilter(NULL);
			//allocate edit buffer
			return true;
		}
	}
	
	//取消Filter
	m_osfLayer->SetSpatialFilter(NULL);
	
	m_pPickedFeature = NULL;
	return false;
}

           

osfOgrVectorLayer.cpp

orsPOINT3D osfOGRVectorLayer::ComputeCentrePoint()
{
	orsPOINT3D tmp_point3d;
	radius = m_filterEnvelope.maxX - m_filterEnvelope.minX;
	//中心点x,y
	tmp_point3d.X = m_filterEnvelope.maxX - radius / 2.0;
	tmp_point3d.Y = m_filterEnvelope.maxY - radius / 2.0;
	return tmp_point3d;
}
int osfOGRVectorLayer::FilterGeometry(osfIGeometry *pGeom)
{
	if(pGeom == NULL||m_pfilterGeom.get() == NULL)
		return true;
	
	osfEnvelope sGeomEnv;
	pGeom->getEnvelope(&sGeomEnv);
	orsPOINT3D centre_p=ComputeCentrePoint();
	bool tmp_sign=pGeom->PointInEnvelope(m_filterEnvelope, centre_p, radius);
	//修改选择方式
	if (!tmp_sign)
		return false;
	else
	{
		if (m_FilterIsEnvelope)
			return true;
		else
			return m_pfilterGeom.get()->Intersects(pGeom);
	}

}
           

osfXLinearRing.cpp

//线段是否在一个区域中。
bool osfXLinearRing::PointInEnvelope(osfEnvelope psEnvelope,orsPOINT3D tmp_point,double radius) const
{
	double min_dis1 = 9999.0;
	double min_dis2 = 9999.0;
	//记录序号。
	int order_point1, order_point2;
	for (int i = 0; i < m_points.size()-1; i++)
	{	
		double tmp_dis1, tmp_dis2;
		tmp_dis1 = sqrt((m_points[i].X - tmp_point.X)*(m_points[i].X - tmp_point.X) + (m_points[i].Y - tmp_point.Y)*(m_points[i].Y - tmp_point.Y));
		tmp_dis2 = sqrt((m_points[i + 1].X - tmp_point.X)*(m_points[i + 1].X - tmp_point.X) + (m_points[i + 1].Y - tmp_point.Y)*(m_points[i + 1].Y - tmp_point.Y));
		//不应该是最近的点,应该是,中间的点。中间点不一定是最近的。
		//应该判断中心点到线段的距离。
		double A = m_points[i + 1].Y - m_points[i].Y;
		double B = m_points[i].X - m_points[i + 1].X;
		double C = m_points[i].Y*m_points[i + 1].X - m_points[i].X*m_points[i + 1].Y;

		double new_dis = abs((A*tmp_point.X + B*tmp_point.Y + C) / (sqrt(A*A + B*B)));

		if (min_new_dis>new_dis)
		{
			order_point1 = i;
			order_point2 = i + 1;
			min_new_dis = new_dis;
		}	

		if (tmp_dis1<min_dis1)
		{
			order_point1 = i;
			min_dis1 = tmp_dis1;
		}
		if (tmp_dis2 < min_dis2)
		{
			order_point2 = i + 1;
			min_dis2 = tmp_dis2;
		}
	}
	if (min_dis1 <= 1.5 * radius || min_dis2 <= 1.5*radius)
	{
		return true;
	}
	else
	{
		double new_dis = abs((m_points[order_point1].Y - m_points[order_point2].Y)*tmp_point.X +
			tmp_point.Y*(m_points[order_point2].X - m_points[order_point1].X) +
			m_points[order_point1].X*m_points[order_point2].Y -
			m_points[order_point2].X*m_points[order_point1].Y) /
			sqrt((m_points[order_point1].Y - m_points[order_point2].Y)*(m_points[order_point1].Y - m_points[order_point2].Y) +
			(m_points[order_point2].X - m_points[order_point1].X)*(m_points[order_point2].X - m_points[order_point1].X)
			);
		if (new_dis<=1.5*radius)
		{
			return true;
		}
		else
		{
			return false;
		}
	}


}
           

代码虽好,三连更爽!!!走起!!!

继续阅读