写了三个选择直线的函数不知道哪一个快(STL)

zhao1zhong6 2009-02-07 05:46:47
为了不让你失去耐心,我尽量让代码简化,如果你没有时间看代码
请直接转到最后一行,问题在那里。
我已经将直线的每个点储存到vector容器中(我已经存好了,
现在要选中它)
这是第一个版本:
bool CObject::CheckSelectLine(const POINT &pt1)
{
if (P->empty()) return false;

vector< POINT >::iterator it=P->begin();

for (; it!=P->end();++it)
{
if ((*it).x==pt1.x||(*it).y==pt1.y)
return true;
}
return false;
}
很简洁不是吗?P是类CObject中的一个成员变量,(你可以把它当成一个
可以改变长度的数组或者链表利用迭代器it遍历容器,
如果点的坐标有重合的就返回true,否则返回false。
但是....如果这条直线有1000个点那就要循环1000次,而且每一次
都要取出成员变量,我觉得这样肯定慢,因此我写了
第二个版本:
bool CObject::CheckSelectLine(const POINT &pt1)
{
if (P->empty()) return false;
vector< POINT >::iterator Head=P->begin();
vector< POINT >::iterator Tail=P->end()-1;
long sx=(*Head).x;//start x
long sy=(*Head).y;//start y
long ex=(*Tail).x;//end x
long ey=(*Tail).y;//end y
long px=pt1.x;
long py=pt1.y;
long vx=abs(ex-sx);//x轴矢量
long vy=abs(ey-sy);//y轴矢量
long vpx=abs(px-sx);
long vpy=abs(py-sy);
if (sx<=ex)//开始点在左边
{
if (px<sx||px>ex)return false;//在区域以外
goto level2;
}
else//if (sx>ex)//开始点在右边
{
if (px<ex||px>sx)return false;//在区域以外
goto level2;
}
level2:
if (sy<=ey)//开始点在上边
{
if (py<sy||py>ey)return false;//在区域以外
goto level3;
}
else//if (sy>ey)开始点在下边
{
if (py<ey||py>sy)return false;//在区域以外
goto level3;
}
level3:
if (vx>=vy)//近x轴
{
if ((*(Head+vpx)).y==py)return true;
}
else//if(vx<vy)近Y轴
{
if ((*(Head+vpy)).x==px)return true;
}

return false;
}
因为我储存直线的时候它的每一个点都是连续的,所以改进后的版本
经过几次判断就可以了,虽然goto语句已经不提倡使用了但它确实
能够减少代码的数量增加可读性,直线是用Bresenham算法储存的
因此要考虑到是近X轴还是近Y轴。你可能会注意到函数开头时申请了
很多变量,这纯粹是为了增加代码的可读性,但是每执行一次这个函数
就要申请这么多变量我觉得有点浪费因此我写了可读性级差的第三个版本:
bool CObject::CheckSelectLine(const POINT &pt1)
{
if (P->empty())
{
return false;
}
vector< POINT >::iterator Head=P->begin();
vector< POINT >::iterator Tail=P->end()-1;
/////////////////////////开始点在左边////////////////////////////
if ((*Head).x<=(*Tail).x)
{
if (pt1.x<(*Head).x||pt1.x>(*Tail).x)
return false;//在X轴区域以外

/////////////////////////开始点在上边////////////////////////////
if ((*Head).y<=(*Tail).y)/////////
{
if (pt1.y<(*Head).y||pt1.y>(*Tail).y)//在Y轴区域以外
return false;

if ((*Tail).x-(*Head).x>=(*Tail).y-(*Head).y)//近X轴
{
if ((*(Head+(pt1.x-(*Head).x))).y==pt1.y)
return true;
}
else//近Y轴
{
if ((*(Head+(pt1.y-(*Head).y))).x==pt1.x)
return true;
}

}
/////////////////////////开始点在下边////////////////////////////
else//
{
if (pt1.y<(*Tail).y||pt1.y>(*Head).y)//在Y轴区域以外
return false;

if ((*Tail).x-(*Head).x>=(*Head).y-(*Tail).y)//近x轴
{
if ((*(Head+(pt1.x-(*Head).x))).y==pt1.y)
return true;
}
else//近Y轴
{
if ((*(Head+((*Head).y-pt1.y))).x==pt1.x)
return true;
}
}
}
/////////////////////////开始点在右边////////////////////////////
else//if ((*Head).x>(*Tail).x)
{
if (pt1.x<(*Tail).x||pt1.x>(*Head).x)
return false;//在X轴区域以外

/////////////////////////开始点在上边////////////////////////////
if ((*Head).y<=(*Tail).y)/////////
{
if (pt1.y<(*Head).y||pt1.y>(*Tail).y)//在Y轴区域以外
return false;

if ((*Head).x-(*Tail).x>=(*Tail).y-(*Head).y)//近X轴
{
if ((*(Head+((*Head).x)-pt1.x)).y==pt1.y)
return true;
}
else//近Y轴
{
if ((*(Head+(pt1.y-(*Head).y))).x==pt1.x)
return true;
}

}
/////////////////////////开始点在下边////////////////////////////
else//
{
if (pt1.y<(*Tail).y||pt1.y>(*Head).y)//在Y轴区域以外
return false;

if ((*Head).x-(*Tail).x>=(*Head).y-(*Tail).y)//近x轴
{
if ((*(Head+((*Head).x-pt1.x))).y==pt1.y)
return true;
}
else//近Y轴
{
if ((*(Head+((*Head).y-pt1.y))).x==pt1.x)
return true;
}
}
}
return false;
}
写完了之后连我自己看了都迷糊,(其实我是先写的第三个版本)
我不知道第三个版本和第二个版本哪一个效率高这是问题的所在,
也就是说利用申请的临时变量来减少取成员变量所耗费的时钟周期
值不值得,请教高人。
...全文
124 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
CodeSpy 2009-02-08
  • 打赏
  • 举报
回复
假设这是平面上的直线,你用某个画线的算法(具体能用哪些算法我也不记得了:D)来绘制这条直线,并存储了要绘制的点。
首先,对这些点按照x,y大小进行排序;然后,进行二分查找。

最后,这条语句if ((*it).x==pt1.x||(*it).y==pt1.y) 的操作手感不好:D
zhao1zhong6 2009-02-07
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 waizqfor 的回复:]
感觉LZ第一个写的就不错!~
[/Quote]
我储存每一个点的初衷就是为了写类似的函数。
zhao1zhong6 2009-02-07
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 hityct1 的回复:]
不知道楼主的用意。“选择直线的函数” 用来干什么的?再说“线段”,只存储两个端点就行了。
[/Quote]
类似于CAD的选择功能。
waizqfor 2009-02-07
  • 打赏
  • 举报
回复
感觉LZ第一个写的就不错!~
hityct1 2009-02-07
  • 打赏
  • 举报
回复
不知道楼主的用意。“选择直线的函数” 用来干什么的?再说“线段”,只存储两个端点就行了。
nineforever 2009-02-07
  • 打赏
  • 举报
回复
你在release模式下测一下时间好了(VC9的vector默认有参数校验,所以可能性能会差一些)
zhao1zhong6 2009-02-07
  • 打赏
  • 举报
回复
我又改进了一下:
bool CObject::CheckSelectLine(const POINT &pt1)
{
if (P->empty()) return false;

vector< POINT >::iterator Head=P->begin();
vector< POINT >::iterator Tail=P->end()-1;
long sx=(*Head).x;//start x
long sy=(*Head).y;//start y
long ex=(*Tail).x;//end x
long ey=(*Tail).y;//end y
long px=pt1.x;
long py=pt1.y;

//判断是否在矩形区域以外
if (px<min(ex,sx)||px>max(ex,sx))return false;
if (py<min(ey,sy)||py>max(ey,sy))return false;

if (abs(ex-sx)>=abs(ey-sy))//近x轴
{
if ((*(Head+abs(px-sx))).y==py)return true;
}
else//近Y轴
{
if ((*(Head+abs(py-sy))).x==px)return true;
}

return false;
}
Proteas 2009-02-07
  • 打赏
  • 举报
回复
好长,好长......
qqwx_1986 2009-02-07
  • 打赏
  • 举报
回复
mark
up
zhao1zhong6 2009-02-07
  • 打赏
  • 举报
回复
bool CObject::CheckSelectLine(const POINT &pt1) 
{
if (P->empty()) return false;
vector < POINT >::iterator Head=P->begin();
vector < POINT >::iterator Tail=P->end()-1;
long sx=(*Head).x;//start x
long sy=(*Head).y;//start y
long ex=(*Tail).x;//end x
long ey=(*Tail).y;//end y
long px=pt1.x;
long py=pt1.y;
long vx=abs(ex-sx);//x轴矢量
long vy=abs(ey-sy);//y轴矢量
long vpx=abs(px-sx);
long vpy=abs(py-sy);
if (sx <=ex)//开始点在左边
{
if (px <sx||px>ex)return false;//在区域以外
goto level2;
}
else//if (sx>ex)//开始点在右边
{
if (px <ex||px>sx)return false;//在区域以外
goto level2;
}
level2:
if (sy <=ey)//开始点在上边
{
if (py <sy||py>ey)return false;//在区域以外
goto level3;
}
else//if (sy>ey)开始点在下边
{
if (py <ey||py>sy)return false;//在区域以外
goto level3;
}
level3:
if (vx>=vy)//近x轴
{
if ((*(Head+vpx)).y==py)return true;
}
else//if(vx <vy)近Y轴
{
if ((*(Head+vpy)).x==px)return true;
}

return false;
}
zhao1zhong6 2009-02-07
  • 打赏
  • 举报
回复
bool CObject::CheckSelectLine(const POINT &pt1) 
{
if (P->empty()) return false;

vector < POINT >::iterator it=P->begin();

for (; it!=P->end();++it)
{
if ((*it).x==pt1.x||(*it).y==pt1.y)
return true;
}
return false;
}
zhao1zhong6 2009-02-07
  • 打赏
  • 举报
回复
#include <windows.h>
#include <math.h>
#include <vector
using namespace std;
typedef vector< POINT > VECPT;
typedef vector< POINT >::iterator ITEPT;
const int SELECTOBJECT=0;
const int DRAWLINE =1;
const int DRAWCIRCLE =2;
const int DRAWRECT =3;
class CObject
{
public:
CObject();
virtual ~CObject();

VECPT *P;

private:
bool m_bSelect;
DWORD m_dwColor;
public:
DWORD GetColor(){return m_dwColor;}
void StoreLine( POINT pt1,POINT pt2);
void StoreCircle(POINT pt1,POINT pt2);
void StoreRect( POINT pt1,POINT pt2);
bool CheckSelectLine(const POINT&);
static void DrawtempRect( POINT,POINT,DWORD color,BYTE * memory,DWORD lpitch);
static void Drawtempline( POINT,POINT,DWORD color,BYTE * memory,DWORD lpitch);
static void DrawtempCircle(POINT,POINT,DWORD color,BYTE * memory,DWORD lpitch);

};

65,210

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧