九桔猫--广纳百川,服务世界(专业思考与实践者)

*互联网应用-机器人-图形学-CAD-机器学习-行业信息化-各种研究

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

近日,有搞数控与CAD的朋友遇到此问题,与本人谈及,遂有兴趣完成此程序。

程序的目标,是从矩形一角出发,沿边界前进,到一个距离后,斜向拐弯,然后遇到边界,沿边界前进一个距离,再拐弯,依次前进,直到最后一个矩形边界。

效果图如下:

该程序看上去很简单,但具体实现起来,需要考虑的细节不少,本人的方法,是直线矩形裁剪算法+绘图起点两侧的vector存储交点,同时交点结构体中有一个标志与下一点是否连线的变量。

 

上代码了 。。。。。

首先,依然是那个坑爹的stdafx.h

#pragma once
#include "targetver.h"

#define WIN32_LEAN_AND_MEAN             //从Windows头中排除极少使用的资料

//C++标准库头文件
#include<vector>
using namespace std;

//Windows 头文件:
#include <windows.h>

//C运行时头文件
#include<stdlib.h>
#include<malloc.h>
#include<memory.h>
#include<tchar.h>
#include<math.h>

//TODO:在此处引用程序需要的其他头文件
#include"myconst.h"
#include"mygraph.h"

紧跟着就是stdafx.cpp

// stdafx.cpp : 只包括标准包含文件的源文件
// sdkRectfill.pch 将作为预编译头
// stdafx.obj 将包含预编译类型信息

#include "stdafx.h"

// TODO: 在 STDAFX.H 中
// 引用任何所需的附加头文件,而不是在此文件中引用

 

 

然后是一直使用但似乎没见到太大作用的targetver.h

#pragma once

// 以下宏定义要求的最低平台。要求的最低平台
// 是具有运行应用程序所需功能的 Windows、Internet Explorer 等产品的
// 最早版本。通过在指定版本及更低版本的平台上启用所有可用的功能,宏可以
// 正常工作。

// 如果必须要针对低于以下指定版本的平台,请修改下列定义。
// 有关不同平台对应值的最新信息,请参考 MSDN。
#ifndef WINVER                          // 指定要求的最低平台是 Windows Vista。
#define WINVER 0x0600           // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif

#ifndef _WIN32_WINNT            // 指定要求的最低平台是 Windows Vista。
#define _WIN32_WINNT 0x0600     // 将此值更改为相应的值,以适用于 Windows 的其他版本。
#endif

#ifndef _WIN32_WINDOWS          // 指定要求的最低平台是 Windows 98。
#define _WIN32_WINDOWS 0x0410 // 将此值更改为适当的值,以适用于 Windows Me 或更高版本。
#endif

#ifndef _WIN32_IE                       // 指定要求的最低平台是 Internet Explorer 7.0。
#define _WIN32_IE 0x0700        // 将此值更改为相应的值,以适用于 IE 的其他版本。
#endif

 

一行语句,包含了资源文件声明的sdkRectfill.h

#pragma once

#include "resource.h"

资源声明的h文件(这个忽略了,因为在VC中新建Win32Application后,自然就有这个了,不必理会)

 

**来正题了**

 

定义了一堆常量的myconst.h,这里大部分是在GUI时由用户输入的。

#ifndef _myconst_h_
#define _myconst_h_

//函数执行是否成功的标识
const int INTOK=1;
const int INTERR=0;

const float PI=3.14159265f;

//设置初始边界变量
const int LEFT=0x0001;
const int RIGHT=0x0010;
const int BOTTOM=0x0100;
const int TOP=0x1000;

//本部分数值实际工程中可由用户输入
/******Begin******/
//测试用初始线段的两端点
const int LINE_START_X=20;
const int LINE_START_Y=10;
const int LINE_END_X=800;
const int LINE_END_Y=400;

//初始矩形的两顶点
const int REC_X_LEFT=40;
const int REC_Y_BOTTOM=50;
const int REC_X_RIGHT=600;
const int REC_Y_TOP=500;

//起始直线倾角
//倾角与绘制起始点也有范围关系,本次暂不做校验
const int ARG_ANGLE=60;
const int ARG_NULL=90;

//在矩形上可选的绘制起点(暂定为自左上角启动)
const int REC_LEFTBOTTOM=1;
const int REC_LEFTTOP=2;
const int REC_RIGHTBOTTOM=3;
const int REC_RIGHTTOP=4;

//直线间距
const int LINE_DIST=30;

//边界填充的初始坐标选择
const int EDGE_X=1;
const int EDGE_Y=2;

/******End******/

#endif

绘图处理函数的声明mygraph.h

#ifndef _mygraph_h_
#define _mygraph_h_

struct newPoint
{
    int x;
    int y;
    int intNextForward;
}myPointStruct;

typedef struct newPoint myPoint; 


//初始化函数
extern int intInitSet(int *,int);

//依据倾角计算斜率的函数声明
extern float flaKCalc(int);

//线段的端点赋值函数声明
extern int intLineset(int *,int *,int *,int *,int,int,int,int);

//判别XY轴增长方向的函数
//暂未考虑倾角的合理性校验
extern int intXYFoward(int *,int *,int);

//根据起始点标志变量计算矩形起始点实际坐标函数声明
extern int intXYStart(int *,int *,int);

//PI/2-倾角的正负校验
extern int intYAngleStepCalc(int);

//对角点坐标计算函数声明
extern int intXYDig(int *,int *,int);

//对角点到起始直线的距离计算函数声明
extern int intPt2LineStartCalc(int,int,int,int,float);

//边界绘制时初始XY两轴交点是否连接的处理函数声明
extern int intXYEdge(int *,int *,int);

//Cohen-Sutherland编码函数声明
extern int cohenCode(int,int);

//Cohen-Sutherland处理函数声明
extern int cohenProcess(int *,int *,int *,int *,int,int,int,int);

#endif

 

绘图处理函数的实现mygraph.cpp

#include<stdafx.h>

//初始化函数
int intInitSet(int *iDst,int iSrc)
{
    *iDst=iSrc;
    return INTOK;
}

//依据倾角计算斜率
float flaKCalc(int intArg)
{
    if((intArg+ARG_NULL)%ARG_NULL)
    {
        return tan(intArg*PI/180);
        
    }
    else
        return (float)INTERR;
}

//线段两端点值的赋值函数
int intLineset(int *pintXNewStart,int *pintYNewStart,int *pintXNewEnd,int *pintYNewEnd,int intXStart,int intYStart,int intXEnd,int intYEnd)
{
    
    *pintXNewStart=intXStart;
    *pintYNewStart=intYStart;
    *pintXNewEnd=intXEnd;
    *pintYNewEnd=intYEnd;
    
    return INTOK;    
}

//判别批量绘制直线时XY轴增长方向的函数
int intXYFoward(int *iXStep,int *iYStep,int intRecStartSet)
{
    switch(intRecStartSet)
    {
    case REC_LEFTBOTTOM:
        *iXStep=1;
        *iYStep=1;
        return INTOK;
    case REC_LEFTTOP:
        *iXStep=1;
        *iYStep=-1;
        return INTOK;
    case REC_RIGHTBOTTOM:
        *iXStep=-1;
        *iYStep=1;
        return INTOK;
    case REC_RIGHTTOP:
        *iXStep=-1;
        *iYStep=-1;
        return INTOK;
    default:
        *iXStep=0;
        *iYStep=0;
        return INTERR;
    }
}

//根据起始点标志变量计算矩形起始点实际坐标函数
int intXYStart(int *iXRecStart,int *iYRecStart,int intPtRecStart)
{
    switch(intPtRecStart)
    {
    case REC_LEFTBOTTOM:
        *iXRecStart=REC_X_LEFT;
        *iYRecStart=REC_Y_BOTTOM;
        return INTOK;
    case REC_LEFTTOP:
        *iXRecStart=REC_X_LEFT;
        *iYRecStart=REC_Y_TOP;
        return INTOK;
    case REC_RIGHTBOTTOM:
        *iXRecStart=REC_X_RIGHT;
        *iYRecStart=REC_Y_BOTTOM;
        return INTOK;
    case REC_RIGHTTOP:
        *iXRecStart=REC_X_RIGHT;
        *iYRecStart=REC_Y_TOP;
        return INTOK;
    default:
        *iXRecStart=0;
        *iYRecStart=0;
        return INTERR;
    }
}

//PI/2-倾角的正负校验
int intYAngleStepCalc(int intRecStartSet)
{
    switch(intRecStartSet)
    {
    case REC_LEFTBOTTOM:
        return -1;
    case REC_LEFTTOP:
        return 1;
    case REC_RIGHTBOTTOM:
        return 1;
    case REC_RIGHTTOP:
        return -1;
    default:
        return INTERR;
    }    
}

//对角点坐标计算函数
int intXYDig(int *iXDig,int *iYDig,int intPtRecStart)
{
    switch(intPtRecStart)
    {
    case REC_LEFTBOTTOM:
        *iXDig=REC_X_RIGHT;
        *iYDig=REC_Y_TOP;
        return INTOK;
    case REC_LEFTTOP:
        *iXDig=REC_X_RIGHT;
        *iYDig=REC_Y_BOTTOM;
        return INTOK;
    case REC_RIGHTBOTTOM:
        *iXDig=REC_X_LEFT;
        *iYDig=REC_Y_TOP;
        return INTOK;
    case REC_RIGHTTOP:
        *iXDig=REC_X_LEFT;
        *iYDig=REC_Y_BOTTOM;
        return INTOK;
    default:
        *iXDig=0;
        *iYDig=0;
        return INTERR;
    }
}

//对角点到起始直线的距离计算
//intXPt:对角点X坐标
//intYPt:对角点Y坐标
//intXInLine:点斜式中所用在直线上的点X坐标
//intYInLine:点斜式中所用在直线上的点Y坐标
//k:直线斜率
int intPt2LineStartCalc(int intXPt,int intYPt,int intXInLine,int intYInLine,float k)
{
    if(k)
    {
        return (int)(fabs(k*intXPt+(-1)*intYPt+intYInLine-k*intXInLine)/sqrt(k*k+1));
    }
    else
        return INTERR;
}

//边界绘制时初始XY两轴交点是否连接的处理函数声明
//iXEdge对应mpAdd一侧的初始状态
//iYEdge对应mpSub一侧的初始状态
int intXYEdge(int *iXEdge,int *iYEdge,int iEdgeForward)
{
    switch(iEdgeForward)
    {
    case EDGE_X:
        *iXEdge=-1;
        *iYEdge=1;
        return INTOK;
    case EDGE_Y:
        *iXEdge=1;
        *iYEdge=-1;
        return INTOK;
    default:
        return INTERR;
    }
}


//Cohen编码函数定义
int cohenCode(int x,int y)
{
    int c=0;
    if(x<REC_X_LEFT)
        c|=LEFT;
    if(x>REC_X_RIGHT)
        c|=RIGHT;
    if(y<REC_Y_BOTTOM)
        c|=BOTTOM;
    if(y>REC_Y_TOP)
        c|=TOP;
    return c;
}

//Cohen裁剪算法处理函数
int cohenProcess(int *pintXNewStart,int *pintYNewStart,int *pintXNewEnd,int *pintYNewEnd,int xs,int ys,int xe,int ye)
{
    int intCode1,intCode2,intCode;
    int x,y;
 
    intCode1=cohenCode(xs,ys);
    intCode2=cohenCode(xe,ye);
 
    while(intCode1!=0||intCode2!=0)
    {
        if((intCode1 & intCode2)!=0)
            return INTERR;
        intCode=intCode1;
        if(intCode1==0)
        {
            intCode=intCode2;
        }
        if((LEFT & intCode)!=0)
        {
            x=REC_X_LEFT;
            y=ys+(ye-ys)*(REC_X_LEFT-xs)/(xe-xs);
        }
        else if((RIGHT & intCode)!=0)
        {
            x=REC_X_RIGHT;
            y=ys+(ye-ys)*(REC_X_RIGHT-xs)/(xe-xs);
        }
        else if((BOTTOM & intCode)!=0)
        {
            y=REC_Y_BOTTOM;
            x=xs+(xe-xs)*(REC_Y_BOTTOM-ys)/(ye-ys);
        }
        else if((TOP & intCode)!=0)
        {
            y=REC_Y_TOP;
            x=xs+(xe-xs)*(REC_Y_TOP-ys)/(ye-ys);
        }
 
        if(intCode==intCode1)
        {
            xs=x;
            ys=y;
            intCode1=cohenCode(x,y);
        }
        else
        {
            xe=x;
            ye=y;
            intCode2=cohenCode(x,y);
        }
    }
    intLineset(pintXNewStart,pintYNewStart,pintXNewEnd,pintYNewEnd,xs,ys,xe,ye); //用处理完毕的xs,ys,xe,ye对线段两端点进行赋值
    return INTOK;
}

 

最终,主文件(sdkRectfill.cpp)出场了,因为有不少是WindowsSDK自动生成的,比较长,默认折叠吧,需要看的朋友请展开。

主要功能,在CREATE和PAINT消息当中完成。

View Code
//sdkRectfill.cpp:定义应用程序的入口点。
//

#include "stdafx.h"
#include "sdkRectfill.h"

/******以下各全局变量最后将检查并进行局部化******/
//Cohen算法处理结果是否成功的标识
int intCohenPro=0;

//线段两个端点变量
int intXLineStart,intYLineStart,intXLineEnd,intYLineEnd;

//交点坐标
int intXAddCross,intYAddCross,intXSubCross,intYSubCross;

//矩形两个定义点变量
int intXRecLeft,intYRecBottom,intXRecRight,intYRecTop;

//绘制直线的倾角与斜率(同时完成初始化)
int intArgAngle=0;
float flaK=0.0f;

//批量绘制工作在矩形上的启动点与方向标识变量
int intPtRecStart=0;

//矩形起始点坐标
int intXRecStart=0;
int intYRecStart=0;

//矩形对角线长度变量
int intRecDiag=0;

//矩形绘制起始点对角点坐标
int intXDig=0;
int intYDig=0;

//绘制过程中直线的间距
int intLineDist=0;

//对角点到起始直线的距离
int intPt2LineStart=0;

//需要绘制的直线个数变量
int intLineCount=0;

//绘制时xy两轴的坐标变化方向变量(将取值为1或-1)
int intXStep=0;
int intYStep=0;

//PI/2-倾角的正负标志变量
int intYAngleStep=0;

//存储批量绘制直线的交点坐标
vector<myPoint>vecAddCross;
vector<myPoint>vecSubCross;

//最终从启动点开始沿XY某坐标轴方向的选择标志变量
int intEdgeForward=0;
int intXEdge=0;
int intYEdge=0;

//**如下部分为Windows程序自有声明及定义**
#define MAX_LOADSTRING 100

HINSTANCE hInst;                                // 当前实例
TCHAR szTitle[MAX_LOADSTRING];                    // 标题栏文本
TCHAR szWindowClass[MAX_LOADSTRING];            // 主窗口类名

//若干基本的函数声明
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE,int);
LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
INT_PTR CALLBACK About(HWND,UINT,WPARAM,LPARAM);

int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);

    MSG msg;
    HACCEL hAccelTable;

    //初始化全局字符串
    LoadString(hInstance,IDS_APP_TITLE,szTitle,MAX_LOADSTRING);
    LoadString(hInstance,IDC_SDKRECTFILL,szWindowClass,MAX_LOADSTRING);
    MyRegisterClass(hInstance);

    //执行应用程序初始化:
    if (!InitInstance (hInstance,nCmdShow))
    {
        return FALSE;
    }

    hAccelTable=LoadAccelerators(hInstance,MAKEINTRESOURCE(IDC_SDKRECTFILL));

    //主消息循环:
    while(GetMessage(&msg,NULL,0,0))
    {
        if (!TranslateAccelerator(msg.hwnd,hAccelTable,&msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
    }
    return (int) msg.wParam;
}


//函数MyRegisterClass():注册窗口类。
ATOM MyRegisterClass(HINSTANCE hInstance)
{
    WNDCLASSEX wcex;
    wcex.cbSize=sizeof(WNDCLASSEX);
    wcex.style=CS_HREDRAW|CS_VREDRAW;
    wcex.lpfnWndProc=WndProc;
    wcex.cbClsExtra=0;
    wcex.cbWndExtra=0;
    wcex.hInstance=hInstance;
    wcex.hIcon=LoadIcon(hInstance,MAKEINTRESOURCE(IDI_SDKRECTFILL));
    wcex.hCursor=LoadCursor(NULL,IDC_ARROW);
    wcex.hbrBackground=(HBRUSH)(COLOR_WINDOW+1);
    wcex.lpszMenuName=MAKEINTRESOURCE(IDC_SDKRECTFILL);
    wcex.lpszClassName=szWindowClass;
    wcex.hIconSm=LoadIcon(wcex.hInstance,MAKEINTRESOURCE(IDI_SMALL));

    return RegisterClassEx(&wcex);
}

//函数InitInstance(HINSTANCE, int)保存实例句柄并创建主窗口
BOOL InitInstance(HINSTANCE hInstance,int nCmdShow)
{
   HWND hWnd;
   hInst=hInstance; // 将实例句柄存储在全局变量中

   hWnd=CreateWindow(szWindowClass,szTitle,WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,0,CW_USEDEFAULT,0,NULL,NULL,hInstance,NULL);
   if(!hWnd)
   {
      return FALSE;
   }
   ShowWindow(hWnd,nCmdShow);
   UpdateWindow(hWnd);

   return TRUE;
}

//函数WndProc: 处理主窗口的消息
LRESULT CALLBACK WndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)
{
    //int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;
    
    switch (message)
    {
    case WM_CREATE:
        /******初始化工作Begin******/
        //矩形坐标初始化
        intInitSet(&intXRecLeft,REC_X_LEFT);
        intInitSet(&intYRecBottom,REC_Y_BOTTOM);
        intInitSet(&intXRecRight,REC_X_RIGHT);
        intInitSet(&intYRecTop,REC_Y_TOP);
        
        //完成绘制直线倾角与启动点及画线间距
        intInitSet(&intArgAngle,ARG_ANGLE);
        intInitSet(&intLineDist,LINE_DIST);

        //初始化批量绘制直线的起始点
        intInitSet(&intPtRecStart,REC_LEFTTOP);
        
        //初始化矩形边界的绘制方向及连接变量
        intInitSet(&intEdgeForward,EDGE_X);
        //intInitSet(&intEdgeForward,EDGE_Y);

        /******End初始化工作******/

        //斜率计算
        flaK=flaKCalc(intArgAngle);
        
        //矩形对角线长度
        intRecDiag=(int)sqrt((float)(intXRecRight-intXRecLeft)*(intXRecRight-intXRecLeft)+(float)(intYRecTop-intYRecBottom)*(intYRecTop-intYRecBottom));

        //完成xy两个坐标轴增长方向的判断
        intXYFoward(&intXStep,&intYStep,intPtRecStart);
        
        //根据绘图的起始点计算出起始点与对角点坐标
        intXYStart(&intXRecStart,&intYRecStart,intPtRecStart);
        intXYDig(&intXDig,&intYDig,intPtRecStart);
        
        //矩形边界绘制初始变量的判断
        intXYEdge(&intXEdge,&intYEdge,intEdgeForward);

        //计算对角点到起始直线的距离
        intPt2LineStart=intPt2LineStartCalc(intXDig,intYDig,intXRecStart,intYRecStart,flaK);
                        
        //结合间距计算直线绘制数量
        intLineCount=intPt2LineStart/intLineDist;
        
        //准备一批待绘制直线的两个端点
        //****步骤*****
        //a-算出从矩形起始点向绘制方向延伸点的坐标
        //b-算出从延伸点向绘制的垂直方向两侧各延伸出对角线长的点坐标
        //c-计算结果存入vector
        vecAddCross.clear();
        vecSubCross.clear();
        
        //垂线中点坐标的初始化
        int intXCenter,intYCenter;
        intXCenter=intXRecStart;
        intYCenter=intYRecStart;
        
        //垂线两侧点的初始化
        myPoint mpAdd;
        myPoint mpSub;
        mpAdd.x=intXCenter;
        mpAdd.y=intYCenter;
        mpSub.x=intXCenter;
        mpSub.y=intYCenter;
                
        //交点坐标结构体变量的声明
        myPoint mpAddCross;
        myPoint mpSubCross;
        for(int i=0;i<intLineCount;i++)
        {
            //先计算在绘制直线的垂线上的中点
            //不同的启动点决定了PI/2-intArgAngle角度正负差异,故使用intYStepAngle校正sin(cos因偶函数性质不需校正)
            intYAngleStep=intYAngleStepCalc(intPtRecStart);
            
            //垂线上各点计算
            intXCenter=(int)(intXRecStart+intXStep*(i+1)*intLineDist*cos((float)(PI/2-intArgAngle*PI/180)));
            intYCenter=(int)(intYRecStart+intYAngleStep*intYStep*(i+1)*intLineDist*sin((float)(PI/2-intArgAngle*PI/180)));

            //计算两侧坐标
            //Add方向更靠近X轴一侧
            //Y增长方向一定与垂线的Y增长方向相反,故*(-1)
            mpAdd.x=(int)(intXCenter+intXStep*intRecDiag*cos(intArgAngle*PI/180));
            mpAdd.y=(int)(intYCenter+(-1)*intYStep*intRecDiag*sin(intArgAngle*PI/180));
            mpSub.x=(int)(intXCenter-intXStep*intRecDiag*cos(intArgAngle*PI/180));
            mpSub.y=(int)(intYCenter-(-1)*intYStep*intRecDiag*sin(intArgAngle*PI/180));
            
            //根据两侧坐标计算裁剪后与矩形的交点
            intXAddCross=mpAdd.x;
            intYAddCross=mpAdd.y;
            intXSubCross=mpSub.x;
            intYSubCross=mpSub.y;
            intCohenPro=cohenProcess(&intXAddCross,&intYAddCross,&intXSubCross,&intYSubCross,intXAddCross,intYAddCross,intXSubCross,intYSubCross);
            
            //Add与Sub获得两个交点坐标
            mpAddCross.x=intXAddCross;
            mpAddCross.y=intYAddCross;
            mpSubCross.x=intXSubCross;
            mpSubCross.y=intYSubCross;

            //分别设定mpAdd与mpSub每一点与下一点是否连接的标志变量
            //直线绘制的起始点为intPtRecStart,故Vector中的第一点实为绘制时的第二点
            //因最后循环时mpSub与mpAdd反方向,故mpAdd与mpSub为配对相等关系
            mpAddCross.intNextForward=intXEdge;
            mpSubCross.intNextForward=intYEdge;
            
            //将两侧裁剪所得交点存入相应的Vector
            vecAddCross.push_back(mpAddCross);
            vecSubCross.push_back(mpSubCross);

            //下次是否连接必然与此次相反
            intXEdge=-intXEdge;
            intYEdge=-intYEdge;
        }
        break;

    case WM_PAINT:
        hdc=BeginPaint(hWnd,&ps);
            
        //绘制矩形
        Rectangle(hdc,intXRecLeft,intYRecBottom,intXRecRight,intYRecTop);
        
        //设定初始及裁剪后线段绘图画笔
        HGDIOBJ hgBlackPen,hgRedPen;
        hgBlackPen=(HGDIOBJ)GetStockObject(BLACK_PEN);
        hgRedPen=CreatePen(PS_SOLID,2,RGB(255,0,0));
            
        //主工作流程
        //(1)-批量绘制直线        
        //绘制裁剪结果之前的画笔准备
        SelectObject(hdc,hgRedPen);
                
        //沿矩形外周循环一圈完成边界交错连接绘制
        //首先需要完成的是启动点和指定坐标轴上第一点的连接
        MoveToEx(hdc,intXRecStart,intYRecStart,NULL);
        if(EDGE_X==intEdgeForward)
        {
            LineTo(hdc,vecAddCross[0].x,vecAddCross[0].y);
        }
        else if(EDGE_Y==intEdgeForward)
        {
            LineTo(hdc,vecSubCross[0].x,vecSubCross[0].y);
        }
        else
        {
            //错误提醒处理
        }
        
        //(2)-分别沿XY两坐标轴方向完成Add与Sub两个方向的交错绘制

        //矩形边角上的直角拐弯处理
        //Add一侧一定是从X相等变到Y相等
        //Sub一侧一定是从Y相等变到X相等        
        for(int i=0;i<intLineCount-1;i++)
        {
            if(1==vecAddCross[i].intNextForward)
            {
                if(vecAddCross[i].y==vecAddCross[i+1].y)
                {
                    MoveToEx(hdc,vecAddCross[i].x,vecAddCross[i].y,NULL);
                    LineTo(hdc,vecAddCross[i+1].x,vecAddCross[i+1].y);
                }
                else
                {
                    MoveToEx(hdc,vecAddCross[i].x,vecAddCross[i].y,NULL);
                    LineTo(hdc,vecAddCross[i+1].x,vecAddCross[i].y);
                    MoveToEx(hdc,vecAddCross[i+1].x,vecAddCross[i].y,NULL);
                    LineTo(hdc,vecAddCross[i+1].x,vecAddCross[i+1].y);
                }

            }
            if(1==vecSubCross[i].intNextForward)
            {
                if(vecSubCross[i].x==vecSubCross[i+1].x)
                {
                    MoveToEx(hdc,vecSubCross[i].x,vecSubCross[i].y,NULL);
                    LineTo(hdc,vecSubCross[i+1].x,vecSubCross[i+1].y);
                }
                else
                {
                    MoveToEx(hdc,vecSubCross[i].x,vecSubCross[i].y,NULL);
                    LineTo(hdc,vecSubCross[i].x,vecSubCross[i+1].y);
                    MoveToEx(hdc,vecSubCross[i].x,vecSubCross[i+1].y,NULL);
                    LineTo(hdc,vecSubCross[i+1].x,vecSubCross[i+1].y);
                }
            }
        }


        //(3)-批量矩形内部对直线的裁剪结果绘制
        for(int i=0;i<intLineCount;i++)
        {
            //绘制裁剪后的结果
            MoveToEx(hdc,vecAddCross[i].x,vecAddCross[i].y,NULL);
            LineTo(hdc,vecSubCross[i].x,vecSubCross[i].y);
        }

        //清除各种GDI资源
        DeleteObject(hgBlackPen);
        DeleteObject(hgRedPen);

        //绘图代码结束
        EndPaint(hWnd, &ps);
        break;
        //return 0;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hWnd,message,wParam,lParam);
    }
    return 0;
}

 

附:上述程序,在Windows7x64,VS2008(关闭增量编译)环境下编译调试通过。

posted on 2012-10-31 23:31  九桔猫  阅读(899)  评论(0编辑  收藏  举报