天天看點

關于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;
		}
	}


}
           

代碼雖好,三連更爽!!!走起!!!

繼續閱讀