📄 track.h
字号:
#ifndef MY_TRACK_H
#define MY_TRACK_H
/* file: track.h
*/
#include "mouse.h"
#include "point.h"
static const float minangle=M_PI*2/3;/* 最小转折点角度 */
static const float minseglen=24.0;/* 最小轨道段长度 */
/* structures */
typedef struct
{
long size;/* number of points in the array */
POINT* point;/* point array */
}TRACK;
static int nWidth;
static int nHeight;
static int nMidWid;
static int nMidHei;
/* 从轨道的转折点列表中加入一个点 */
static POINT* PushPoint(TRACK* pTrack, POINT* pPoint)
{
/* 将点加在末尾 */
pTrack->point[pTrack->size].x=pPoint->x;
pTrack->point[pTrack->size].y=pPoint->y;
/* 容量加一,并返回末尾元素地址 */
return &pTrack->point[(pTrack->size)++];
}/*end PushPoint*/
/* 从轨道的转折点列表中删除一个点 */
static POINT* PopPoint(TRACK* pTrack)
{
if( pTrack->size > 0 )
{
/* 容量减一 */
--(pTrack->size);
if( pTrack->size > 0 )
{
/* 返回末尾元素地址 */
return &pTrack->point[pTrack->size-1];
}/*end if*/
}/*end if*/
return NULL;
}/*end PopPoint*/
/* 绘制整个轨道 */
static void DrawTrack(const TRACK* pTrack, BOOL bClose)
{
POINT* pLast=&pTrack->point[pTrack->size-1];
POINT* pPoint;
for( pPoint=&pTrack->point[1]; pPoint<=pLast; ++pPoint )
{
line(pPoint->x,pPoint->y,(pPoint-1)->x,(pPoint-1)->y);
}/*end for*/
if( bClose )/* 首尾连接 */
{
line(pLast->x,pLast->y,pTrack->point[0].x,pTrack->point[0].y);
}/*end if*/
}/*end DrawTrack*/
/* 选择一个已有轨道 */
static TRACK* Select(const TRACK* pTrack,int num)
{
int i;
cleardevice();
setbkcolor(BLACK);
settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
setcolor(YELLOW);
outtextxy(20,80,"Select a track");
setcolor(LIGHTRED);
outtextxy(10,130,"<- : Last Track");
outtextxy(10,170,"-> : Mext Track");
setcolor(LIGHTCYAN);
outtextxy(10,210,"Enter : Select");
outtextxy(10,250,"ESC : Quit");
setcolor(RED);
DrawTrack(pTrack,TRUE);
for( i=0; ; )
{
switch( (char)(getch()) )
{
case 75:/* <- : Last */
{
if( --i < 0 )
{
i=num-1;
}/*end if*/
/* 涂掉原有轨道 */
setfillstyle(SOLID_FILL,BLACK);
bar(nWidth-nHeight+36,36,nWidth-37,nHeight-37);
/* 绘制新轨道 */
setcolor(RED);
DrawTrack(pTrack+i,TRUE);
}break;
case 77:/* -> : Next */
{
if( ++i >= num )
{
i=0;
}/*end if*/
/* 涂掉原有轨道 */
setfillstyle(SOLID_FILL,BLACK);
bar(nWidth-nHeight+36,36,nWidth-37,nHeight-37);
/* 绘制新轨道 */
setcolor(RED);
DrawTrack(pTrack+i,TRUE);
}break;
case '\r':/* Enter */
{
/* 返回选定的轨道元素地址 */
return pTrack+i;
}break;
case 27:/* Esc */
{
return NULL;
}break;
default:{
}break;
}/*end switch*/
}/*end for*/
return NULL;
}/*end Select*/
/* 绘制自定义轨道 */
static TRACK* Customize(TRACK* pTrack)
{
POINT MousePos;/* 当前鼠标坐标 */
POINT LastMPos;/* 上次鼠标坐标 */
POINT* pLast=NULL;/* 最后一次确定的转折点 */
BOOL bMouseMove;/* 鼠标是否移动 */
BOOL bActive;/* 是否有绘图动作 */
BOOL bValid;/* 当前这段轨道是否有效 */
int nState;/* 鼠标按键状态 */
BOOL bLastRButton=FALSE;
float th;
char s[32];
cleardevice();
setbkcolor(BLACK);
InitMouse();/* 初始化鼠标 */
/* 设置鼠标移动范围 */
SetCursorRange(nWidth-nHeight+36,nWidth-37,36,nHeight-37);
settextstyle(DEFAULT_FONT,HORIZ_DIR,1);
setcolor(YELLOW);
outtextxy(20,40,"Use Mouse to");
outtextxy(20,60,"draw your track");
setcolor(LIGHTRED);
outtextxy(10,100,"Left Button :");
outtextxy(10,140,"Right Button :");
setcolor(WHITE);
outtextxy(10,115,"Confirm current point");
outtextxy(10,155,"Delete last point");
setcolor(LIGHTCYAN);
outtextxy(10,190,"Drag the mouse to");
outtextxy(10,205,"draw a curve");
setcolor(BROWN);
outtextxy(10,240,"C : Clear the track");
outtextxy(10,270,"R : Redraw the track");
outtextxy(10,300,"Enter : Finish");
outtextxy(10,330,"ESC : Quit");
setcolor(LIGHTGREEN);
outtextxy(20,380,"Mouse Position");
GetMouseState(&LastMPos);
MousePos=LastMPos;
ShowCursor(&MousePos);
sprintf(s,"%d, %d",MousePos.x,MousePos.y);
setcolor(LIGHTGREEN);
outtextxy(44,395,s);
setvisualpage(0);
for( ; ; delay(1000) )
{
LastMPos=MousePos;
/* 获取鼠标位置及按键状态 */
nState=GetMouseState(&MousePos);
/* 判断鼠标是否移动 */
bActive=bMouseMove=( LastMPos.x != MousePos.x ) || ( LastMPos.y != MousePos.y );
if( pLast != NULL )
{
/* 当前这段轨道长度大于 最小长度,则有效 */
bValid=( Distance(pLast,&MousePos) > minseglen );
if( bValid )
{
if( pTrack->size > 1 )
{
th=Angle(pLast-1,pLast,&MousePos);
/* 轨道转折点的角度足够大(>2pi/3),则有效 */
bValid=bValid&&( th>minangle || th<-minangle );
}/*end if*/
}/*end if*/
}/*end if*/
if( bMouseMove )
{
/* 显示鼠标坐标 */
sprintf(s,"%d , %d",MousePos.x,MousePos.y);
setfillstyle(SOLID_FILL,BLACK);
bar(44,395,115,402);
setcolor(LIGHTGREEN);
outtextxy(44,395,s);
ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */
if( pLast != NULL )
{
/* 清除上次绘制的一段轨道 */
setcolor(BLACK);
line(pLast->x,pLast->y,LastMPos.x,LastMPos.y);
/* 绘制当前这段轨道,无效为灰色,有效为红色 */
setcolor((bValid)?RED:LIGHTGRAY);
line(pLast->x,pLast->y,MousePos.x,MousePos.y);
}/*end if*/
}/*end if*/
if( nState&2 )/* 鼠标右键按下 */
{
if( !bLastRButton )
{
bLastRButton=TRUE;
/* 删除上次确定的转折点 */
if( pTrack->size > 1 )/* 当前轨道有两个以上的转折点 */
{
setcolor(BLACK);
/* bActive==TRUE说明有绘图动作,需重绘鼠标 */
if( !bActive )
{
bActive=TRUE;
ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */
}/*end if*/
/* 清除上次绘制的一段轨道 */
line(pLast->x,pLast->y,MousePos.x,MousePos.y);
/* 清除上上次绘制的一段轨道 */
line(pLast->x,pLast->y,(pLast-1)->x,(pLast-1)->y);
/* 删除末尾的点 */
pLast=PopPoint(pTrack);
/* 判断当前欲绘制的新轨道是否有效 */
bValid=( Distance(pLast,&MousePos) > minseglen );
if( bValid )
{
if( pTrack->size > 1 )
{
th=Angle(pLast-1,pLast,&MousePos);
bValid=bValid&&( th>minangle || th<-minangle );
}/*end if*/
}/*end if*/
/* 绘制当前这段轨道,无效为灰色,有效为红色 */
setcolor((bValid)?RED:LIGHTGRAY);
line(pLast->x,pLast->y,MousePos.x,MousePos.y);
}
else if( pTrack->size == 1 )/* 当前轨道只有一个转折点 */
{
setcolor(BLACK);
if( !bActive )
{
bActive=TRUE;
ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */
}/*end if*/
/* 清除上次绘制的一段轨道 */
line(pLast->x,pLast->y,MousePos.x,MousePos.y);
/* 删除末尾的点 */
pLast=PopPoint(pTrack);
}/*end if*/
}/*end if*/
}
else {
bLastRButton=FALSE;
if( nState&1 )/* 鼠标左键按下 */
{
/* 如果当前没有转折点 或 转折点有效,则确定当前点为转折点 */
if( ( pLast == NULL ) || bValid )
{
if( pTrack->size < 1024 )
{
pLast=PushPoint(pTrack,&MousePos);
}
else {
goto finish;
}/*end if*/
}/*end if*/
}/*end if*/
}/*end if*/
if( bioskey(1) )/* 有键按下 */
{
switch( (char)(getch()) )
{
case 'c':
case 'C':/* Clear the track */
{
if( !bActive )
{
bActive=TRUE;
ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */
}/*end if*/
/* 涂掉原有轨道 */
setfillstyle(SOLID_FILL,BLACK);
bar(nWidth-nHeight+36,36,nWidth-37,nHeight-37);
/* 清除轨道所有转折点 */
pTrack->size=0;
pLast=NULL;
}break;
case 'r':
case 'R':/* Redraw the track */
{
if( !bActive )
{
bActive=TRUE;
ShowCursor(&LastMPos);/* 清除上次绘制的鼠标 */
}/*end if*/
/* 重绘原有轨道 */
setcolor(RED);
DrawTrack(pTrack,FALSE);
/* 重绘当前这段轨道 */
if( !bValid )
{
setcolor(LIGHTGRAY);
line(pLast->x,pLast->y,MousePos.x,MousePos.y);
}/*end if*/
}break;
case '\r':/* Enter */
{
if( pTrack->size >= 3 )
{
finish: if( ( pTrack->point[0].x == pLast->x ) && ( pTrack->point[0].y == pLast->y ) )
{
pLast=PopPoint(pTrack);
if( pTrack->size < 3 )
{
break;
}/*end if*/
}/*end if*/
if( !bActive )
{
ShowCursor(&MousePos);/* 清除上次绘制的鼠标 */
}/*end if*/
/* 清除上次绘制的一段轨道 */
setcolor(BLACK);
line(pLast->x,pLast->y,MousePos.x,MousePos.y);
/* 重绘轨道,首尾连接 */
setcolor(RED);
DrawTrack(pTrack,TRUE);
setfillstyle(SOLID_FILL,BLUE);
bar(nMidWid-120,nMidHei-20,nMidWid+120,nMidHei+20);
setcolor(YELLOW);
outtextxy(nMidWid-80,nMidHei-4,"Press Any Key to Run");
getch();
return pTrack;
}/*end if*/
}break;
case 27:/* Esc */
{
return NULL;
}break;
default:{
}break;
}/*end switch*/
}/*end if*/
if( bActive )
{
ShowCursor(&MousePos);/* 在新位置绘制鼠标 */
}/*end if*/
}/*end for*/
return pTrack;
}/*end Customize*/
#endif /*define MY_TRACK_H*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -