在对OpenRS进行,矢量数据处理的测试时,发现的问题。以OpenRS中矢量图层中移动顶点功能为例,如下图菜单所示。 在矢量的一级菜单下面有着移动顶点,插入顶点,删除单个顶点以及删除框选顶点等功能操作。
在进行这些操作中都需要选中待处理的目标矢量,如下图所示:在1位置处的红色矢量未被选中,在2位置处的矢量为选中状态。
****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; } } }代码虽好,三连更爽!!!走起!!!