📄 arxclip.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 + -