⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 arxclip.cpp

📁 这是书上的代码
💻 CPP
字号:
//
//arxhide.cpp
//本程序于2001年1月15日由梅树立编写。
//本程序有以下功能:1.裁剪MSL_clip 2. 覆盖MSL_hide

//2004年3月27日改写.主要修改内容:窗口可以带内空.
//

#include "stdafx.h"
#include"arxclip.h"

void initApp() //向AutoCAD中加载时调用 该函数
{ 
	acedRegCmds->addCommand("MSL_hide","MSL_hide","MSL_hide",ACRX_CMD_MODAL,windowhide);
	acedRegCmds->addCommand("MSL_clip","MSL_clip","MSL_clip",ACRX_CMD_MODAL,windowcliping);
}

void unloadApp()
{
	acedRegCmds->removeGroup("Trim_hide");
	acedRegCmds->removeGroup("MSL_hide");
}
//应用程序主体
extern "C" AcRx::AppRetCode
acrxEntryPoint(AcRx::AppMsgCode msg,void* pkt)
{
	switch(msg){
		//	处理由AutoCAD传递来的消息
	case AcRx::kInitAppMsg:
		//对应用程序初始化消息的处理
		//调用initApp函数
		acrxDynamicLinker->unlockApplication(pkt);
		//解锁应用程序
		initApp();
		break;
	case  AcRx::kUnloadAppMsg:
		//对应用程序卸载消息的处理
		//调用unloadApp()函数
		unloadApp();
		break;
		
	}
	
	return AcRx::kRetOK;//返回值为AcRx::kRetOk
	
}


//============================窗口裁剪windowclip()======================================
//该程序可完成任意复杂凸形窗口的直线段剪取运算。运行命令为"clip"。程序运行时,首先由用户
//指定在屏幕上画出任意凸形窗口,该窗口可由直线段、圆弧、样条曲线等组成。该程序于2001年1月
//15日由梅树立编写。版权所有,不得拷贝。
//======================================================================================
void pointcpy(ads_point NewPts,ads_point OldPts)
{
	NewPts[X]=OldPts[X];
	NewPts[Y]=OldPts[Y];
	NewPts[Z]=OldPts[Z];
}


void getla_duandian(ads_name ent,ads_point startpts,ads_point endpts,ads_point center)
{
	struct resbuf *ebuf,*eb1,*eb2,*eb3,*eb4;
	int flag;//0:圆弧;1-直线
	char type[20];
	ads_real r,angs,ange;

	getype(ent,type);
	if(strcmp(type,"LINE")==0) flag=1;
	else if(strcmp(type,"ARC")==0) flag=2;
	else flag=0;

	ebuf=acdbEntGet(ent);
	if(flag==1) {
		eb1=entitem(ebuf,10);
		eb2=entitem(ebuf,11);
		pointcpy(startpts,eb1->resval.rpoint);
		pointcpy(endpts,eb2->resval.rpoint);
		center[X]=-1000.0;
		center[Y]=-1000.0;
	}
	else if(flag==2) {
		eb1=entitem(ebuf,10);
		eb2=entitem(ebuf,40);
		eb3=entitem(ebuf,50);
		eb4=entitem(ebuf,51);
		pointcpy(center,eb1->resval.rpoint);
		r=eb2->resval.rreal;
		angs=eb3->resval.rreal;
		ange=eb4->resval.rreal;
		startpts[X]=center[X]+r*cos(angs);
		startpts[Y]=center[Y]+r*sin(angs);
		startpts[Z]=0.0;
		endpts[X]=center[X]+r*cos(ange);
		endpts[Y]=center[Y]+r*sin(ange);
		endpts[Z]=0.0;
	}
	else if(flag==0) {
		eb1=entitem(ebuf,10);
		eb2=entitem(ebuf,40);
		pointcpy(center,eb1->resval.rpoint);
		r=eb2->resval.rreal;
		startpts[X]=endpts[X]=center[X];
		startpts[Y]=endpts[Y]=center[Y]-r;
	}
	acutRelRb(ebuf);
}

//*************************************************************
//利用射线法判断一点是否在窗口内,如果在内部返回1,否则返回0
//其中输入参数pt是被判断点,boundarypt是辅助边界点,用于作射线用
//*********************1-14-2001 by Meishuli

int inwindow(ads_point pt,ads_point boundarypt,ads_name windowent)
{
	ads_name ent0;
	int rt;

	AcDbEntity *pent,*pwindowent;
    AcDbObjectId pentId,pwindowentId;
	AcGePoint3dArray points;
	int CrossPtsNum;
	AcGePoint3d Pts,BoundaryPts;
	AcDbObjectId auxlineId;
    Acad::ErrorStatus es;

	Pts.set(pt[X],pt[Y],0);
	BoundaryPts.set(boundarypt[X],boundarypt[Y],0);

	auxlineId=createLine(Pts,BoundaryPts); 
	acdbEntLast(ent0);

	pwindowent=selectEntity(pwindowentId,windowent,AcDb::kForRead);
	pent=selectEntity(pentId,ent0,AcDb::kForRead);

	es=pwindowent->intersectWith(pent,AcDb::kOnBothOperands,points,0,0);
    if (es == Acad::eOk) {
	    CrossPtsNum=points.length(); //计算交点的数量CrossPtsNum
        points.setLogicalLength(0);
	}
	else {
        acutPrintf("\nerror!--inwindow()\n");

	    pent->close();
		acdbEntDel(ent0);
	    pwindowent->close();
		return -1;
	}
	pent->close();
	acdbEntDel(ent0);

	pwindowent->close();
	if(CrossPtsNum % 2 == 0)
	   rt = 0;
	else rt = 1;
	return rt;
}




//创建直线段
AcDbObjectId
createLine(AcGePoint3d startPt,AcGePoint3d endPt)
{
   AcDbLine *pLine = new AcDbLine(startPt, endPt);

    AcDbBlockTable *pBlockTable;
    acdbHostApplicationServices()->workingDatabase()
        ->getSymbolTable(pBlockTable, AcDb::kForRead);

    AcDbBlockTableRecord *pBlockTableRecord;
    pBlockTable->getAt(ACDB_MODEL_SPACE, pBlockTableRecord,
        AcDb::kForWrite);
    pBlockTable->close();

    AcDbObjectId lineId;
    pBlockTableRecord->appendAcDbEntity(lineId, pLine);

    pBlockTableRecord->close();
    pLine->close();

    return lineId;
}



//将ads_name数据类型转化为对象指针
AcDbEntity *selectEntity(AcDbObjectId &eId,ads_name ent,AcDb::OpenMode openMode)
{
	acdbGetObjectId(eId,ent);//映射ads_name到objectId
	AcDbEntity *pEnt;
	acdbOpenObject(pEnt,eId,openMode); //以OpenMode模式打开eId指向的对象
	return pEnt; //函数返回选中对象的指针
}


bool selectwindow(ads_name ssname, ads_name windowent,char *msg)
// ssname: 当前窗口所有的图形选择集
{
	ads_name ss,ent;
	long len,i;

	acedSSAdd(NULL,NULL,ss);//创建选择集ss
	acutPrintf(msg);
	acedSSGet(NULL,NULL,NULL,NULL,ss);

	if(acedSSLength(ss,&len)!=RTNORM)
		return false;
	if(len <= 0) return false;

	for(i=0;i<len;i++){
		acedSSName(ss,i,ent);
		acedSSDel(ent,ssname); //将窗口选择集从所有选择集中移除
	}

	acedCommand(RTSTR,"REGION",RTPICKS,ss,RTSTR,"",0);

	acdbEntLast(windowent);
	acedSSFree(ss);
	return true;
}



void windowclip(int hide_clip) //hide_clip=1:hide; hide_clip=0:clip
{
	//首先获取当前图形中的所有实体
	struct resbuf rb1,rb2;
	ads_point LeftDownPts,RightUpPts;
	ads_name ssname,windowent,ent;
	ads_name regionent,windowentcopy;
	int rt;
    ads_point ptres,startpts,endpts,center;
	long len,i;
	char type[20];
	
	
    double val0,val1,val2;
	int CrossPtsNum1,n;//交点数
	
	AcDbEntity *pWindowent,*pent;
    AcDbObjectId pWindowentId,pentId;
	AcGePoint3dArray points,points1;
	AcGePoint3d StartPts,EndPts;
	
	acedCommand(RTSTR,"ZOOM",RTSTR,"ALL",0);
	acedGetVar("EXTMAX",&rb1); //获取当前图形右上角点坐标
	acedGetVar("EXTMIN",&rb2); //获取当前图形左下角点坐标
	pointcpy(LeftDownPts,rb2.resval.rpoint);
	pointcpy(RightUpPts,rb1.resval.rpoint);
	
	
	rt=acedSSGet("C",RightUpPts,LeftDownPts,NULL,ssname);
	if(rt!=RTNORM) {
		acdbFail("被裁剪实体选择集构造失败");
		return;
	}
	
	ads_name outent,inent;

	selectwindow(ssname,outent,"请选择外窗口:\n");     //选择外窗口
	while(selectwindow(ssname,inent,"请选择内孔:\n")==true)  //选择内窗口
        acedCommand(RTSTR,"SUBTRACT",RTENAME,outent,RTSTR,"",RTENAME,inent,RTSTR,"",0);
	acdbEntLast(windowent);

	
	pWindowent=selectEntity(pWindowentId,windowent,AcDb::kForRead);
	
	
    //下面求直线段和窗口边界的交点
	ptres[0] = ptres[1] = ptres[2] = 0;
	acedSSLength(ssname,&len);
	for(i=0;i<len;i++) {
		acedSSName(ssname,i,ent);
		getype(ent,type);
		//===================================
		if(strcmp(type,"LINE")) { //如果实体不是直线
			if(!strcmp(type,"CIRCLE")) {//如果是圆
				acedCommand(RTSTR,"REGION",RTENAME,ent,RTSTR,"",0);
				acdbEntLast(regionent);
				acedCommand(RTSTR,"copy",RTENAME,windowent,RTSTR,"",RT3DPOINT,ptres,RTSTR,"",0);
				acdbEntLast(windowentcopy);
				if(hide_clip==1) //覆盖
					acedCommand(RTSTR,"subtract",RTENAME,regionent,RTSTR,"",RTENAME,windowentcopy,RTSTR,"",0);
                else if(hide_clip==0) //剪取
					acedCommand(RTSTR,"intersect",RTENAME,regionent,RTENAME,windowentcopy,RTSTR,"",0);
			}
			continue;
		}
	
		getla_duandian(ent,startpts,endpts,center);
		
		pent=selectEntity(pentId,ent,AcDb::kForRead);
		pWindowent->intersectWith(pent,AcDb::kOnBothOperands,points,0,0);
		CrossPtsNum1=points.length(); //计算交点的数量CrossPtsNum
		if(CrossPtsNum1==0) {//如果没有交点(直线在窗口内部或外部)
			rt=inwindow(startpts,RightUpPts,windowent);
			if(rt==1) {//直线在窗口内部
				pent->close();
				if(hide_clip==1) acdbEntDel(ent);
			}
			else if(rt==0) {//直线在窗口外部
				pent->close();
				if(hide_clip==0) acdbEntDel(ent);
			}
			else if(rt==-1) {//判断错误
				pent->close();
				pWindowent->close();
				return;
			}   
		}
		else {
			val0=(double)(CrossPtsNum1)*0.5;
			val1=modf(val0,&val2);
			StartPts.set(startpts[X],startpts[Y],0);
			EndPts.set(endpts[X],endpts[Y],0);
			
			points.append(StartPts);
			points.append(EndPts);
			
			//=====================================排序=======================
			AcGePoint3d middle,small_pts;
			register j,ii,i0;
			
			n=points.length();
			
			for(j=0;j<n;j++){
				small_pts.set(points[j].x,points[j].y,0);
				ii=j;
				if(fabs(points[0].x-points[n-1].x)>fabs(points[0].y-points[n-1].y)){
					for(i0=j+1;i0<n;i0++){
						if((points[i0].x-small_pts.x)<-DELTA){
							small_pts.set(points[i0].x,points[i0].y,0);
							ii=i0;
						}
					}
				}
				else{
					for(i0=j+1;i0<n;i0++){
						if((points[i0].y-small_pts.y)<-DELTA){
							small_pts.set(points[i0].x,points[i0].y,0);
							ii=i0;
						}
					}
				}
				middle.set(points[j].x,points[j].y,0);
				points[j].set(small_pts.x,small_pts.y,0);
				points[ii].set(middle.x,middle.y,0);
			}
			//=====================================排序结束============================
			
			if(fabs(val1)<0.000001) {//交点数CrossPtsNum1是偶数,直线两端点均在内或均在外
				rt=inwindow(startpts,RightUpPts,windowent);
				if(rt==1) {//均在内部
					if(hide_clip==0) {
					    for(n=0;n<=CrossPtsNum1;n+=2)
						    createLine(points[n],points[n+1]);
					}
					else {
						for(n=1;n<CrossPtsNum1;n+=2)
							createLine(points[n],points[n+1]);
					}
				}
				else {//均在外部
					if(hide_clip==0) {
						for(n=1;n<CrossPtsNum1;n+=2)
							createLine(points[n],points[n+1]);
					}
					else {
						for(n=0;n<=CrossPtsNum1;n+=2)
							createLine(points[n],points[n+1]);
					}
				}
			}
			else {//交点数CrossPtsNum1是奇数,一端点在内另一端点在外
				startpts[X]=points[0].x;
				startpts[Y]=points[0].y;
				startpts[Z]=points[0].z;
				rt=inwindow(startpts,RightUpPts,windowent);
				if(rt==1) {//起点在内
					if(hide_clip==0){
						for(n=0;n<CrossPtsNum1;n+=2)
							createLine(points[n],points[n+1]);
					}
					else {
						for(n=1;n<=CrossPtsNum1;n+=2)
							createLine(points[n],points[n+1]);
					}
				}
				else {//起点在外
					if(hide_clip==0) {
						for(n=1;n<=CrossPtsNum1;n+=2)
							createLine(points[n],points[n+1]);
					}
					else {
						for(n=0;n<CrossPtsNum1;n+=2)
							createLine(points[n],points[n+1]);
					}
				}
			}
			pent->close();
			acdbEntDel(ent);
		}
        points.setLogicalLength(0);
        points1.setLogicalLength(0);
	}
	pWindowent->close();
}


void windowhide()
{
	int hide_clip=1;
	windowclip(hide_clip);
}

void windowcliping()
{
	int hide_clip=0;
	windowclip(hide_clip);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -