關于OpenRS矢量選擇錯誤的修改
- 矢量選擇錯誤情況概述
-
- OpenRS問題概述
- 錯誤修改
矢量選擇錯誤情況概述
在對OpenRS進行,矢量資料處理的測試時,發現的問題。以OpenRS中矢量圖層中移動頂點功能為例,如下圖菜單所示。
在矢量的一級菜單下面有着移動頂點,插入頂點,删除單個頂點以及删除框選頂點等功能操作。
在進行這些操作中都需要選中待處理的目标矢量,如下圖所示:在1位置處的紅色矢量未被選中,在2位置處的矢量為選中狀态。
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;
}
}
}
代碼雖好,三連更爽!!!走起!!!