Java+AutoCAD-逻辑关系关联

Dxf文件中的各种数据,相互之间是没有逻辑关系的。你只是看到他们摆在那里,好像是连在一起的,这只是从视觉的角度,而从数据的角度来讲,相互之间没有关系。

要建立图元之间的关系,就得从本身的业务出发,首先确定用到的到底有几个图元,然后建立这几个图元之间的关系。

我的业务,用到的有直线图元、多线段图元(实际是个矩形)、多行文字图元。

多行文字图元,有两种,一种位置上位于多线段图元的内部,要作为多线段图元的属性;另外一种,位于直线的附近,需要作为直线的属性。

而直线,需要给两端建立实体,这种实体一种是多线段图元,第二种是虚拟的,需要手工创建。

最终按直线的属性输出数据。

1、建立多线段图元和多行文字图元的关联关系

多线段图元的类是YxxfEntLwpolyline,本文中指有四个点的多线段图元,四个点指四边形的四个点。多行文字图元指YxxfEntMtext,只有一个坐标。判断多行文字图元是否在多线段图元的内容,就判断四个坐标点和一个坐标点关系。如果YxxfEntMtext的点坐标都在YxxfEntLwpolyline四个点坐标之间,则为在其内部。

       //取多线段图元的横坐标和纵坐标的最小值和最大值

double x1=999999999,//最小横坐标

                  x2=-999999999,//最大横坐标

                  y1=999999999,//最小纵坐标

                  y2=-999999999;//最大纵坐标

          

      for(int i=0;i<</span>pline.vtxEntities.size();i++){

                YxxfEntVertex vertex = (YxxfEntVertex)pline.vtxEntities.get(i);

                if(x1>vertex.pnt.x)x1=vertex.pnt.x;

                if(x2<</span>vertex.pnt.x)x2=vertex.pnt.x;

                if(y1>vertex.pnt.y)y1=vertex.pnt.y;

                if(y2<</span>vertex.pnt.y)y2=vertex.pnt.y;

      }

 

//遍历所有的YxxfEntMtext,并判断其是否在YxxfEntLwpolyline的内部,如果在内部,则为text赋值。

    YxxfEntBlock blk = D.secEntities.insMSpace.block;

    YxxfEnt ent = null;

   int nextToDraw = 0;

    while (true)

    {

        ent = (YxxfEnt)blk.nextEntity(nextToDraw);

      if (ent == null)

            break;

           

        if(ent.getClass()==YxxfEntMtext.class){//多行文字图元

                   YxxfEntMtext entMtext = (YxxfEntMtext)ent;

                     //判断坐标关系

                   if(entMtext.inspnt.x>=x1 && entMtext.inspnt.x<=x2

                                 && entMtext.inspnt.y>=y1 && entMtext.inspnt.y<=y2){

                          text = entMtext.text;//设置文本

                          entMtext.objId = id;//关联对象的id

                          break;

                   }

        }

        nextToDraw++;

}

2、建立多线段图元和直线图元的关联关系

多线段图元的类是YxxfEntLwpolyline,本文的实例中有四个点;直线图元指YxxfEntLine,有两个坐标点,起点和终点。建立多线段图元和直线图元的关联关系,采用的方法是取YxxfEntLwpolyline的中心点,然后查找距离YxxfEntLine的起点或终点最近的点,然后挂接到YxxfEntLine上。

计算两个点(x1,y1)和(x2,y2)的距离,计算公式是:((x1-x2)^2+(y1-y2)^2)^0.5.

          double x1=999999999,//最小横坐标

                  x2=-999999999,//最大横坐标

                  y1=999999999,//最小纵坐标

                  y2=-999999999;//最大纵坐标

           for(int i=0;i<</span>pline.vtxEntities.size();i++){

                  YxxfEntVertex vertex = (YxxfEntVertex)pline.vtxEntities.get(i);

                  if(x1>vertex.pnt.x)x1=vertex.pnt.x;

                  if(x2<</span>vertex.pnt.x)x2=vertex.pnt.x;

                  if(y1>vertex.pnt.y)y1=vertex.pnt.y;

                  if(y2<</span>vertex.pnt.y)y2=vertex.pnt.y;

           }

           //中心点的坐标=小的坐标+距离的一半

           double x = (x2-x1)/2 + x1;

           double y = (y2-y1)/2 + y1;

          double minLength = 999999999;//最短距离

           int minType = 0;//直线上的点的类型 1起点 2终点

           YxxfEntLine minEnt = null;//距离最短的对象

          YxxfEntBlock blk = D.secEntities.insMSpace.block;

           YxxfEnt ent = null;

          int nextToDraw = 0;

     while (true)

     {

         ent = (YxxfEnt)blk.nextEntity(nextToDraw);

       if (ent == null)

                break;

       if(ent.getClass()==YxxfEntLine.class){//直线类型

                   YxxfEntLine entLine = (YxxfEntLine)ent;

                   //计算两点间的距离

                   double tmp1 = Math.sqrt(Math.pow(entLine.begpnt.x-x, 2)+Math.pow(entLine.begpnt.y-y, 2));//起点

                   if(minLength>tmp1){

                          minLength = tmp1;

                          minType = 1;

                          minEnt = entLine;

                   }

                  

                   double tmp2 = Math.sqrt(Math.pow(entLine.endpnt.x-x, 2)+Math.pow(entLine.endpnt.y-y, 2));//终点

                   if(minLength>tmp2){

                          minLength = tmp2;

                          minType = 2;

                          minEnt = entLine;

                   }

         }

         nextToDraw++;

     }

        if(minType==1)minEnt.begObj = this;

        else if(minType==2)minEnt.endObj = this;

3、建立剩余多行文字图元和直线图元的关联关系

一部分多行文字图元在上面已经挂在了多线段图元上,剩余的部分,需要挂在直线上,成为直线的一个属性。

直线有两个坐标点,根据斜率的不同,可以有横向的和纵向的。多行文字有一个坐标点,也有横向的纵向的。首先判断多行文字图元是横向的还是纵向的,然后如果是横向的,循环处理所有的横向直线;如果是纵向的,则循环处理所有的纵向直线。取距离最短的,距离最短的计算方法是取点到直线的垂直距离。这个垂直距离的计算方法在“6、点到直线的垂直距离计算方法”中有详细的描述。

 public String objId = null;//关联的对象的id

 if(objId!=null) return;//已经有管理对象的,不用再处理了

 if(text==null || text.equals("")) return;//没有数据,不用处理

          //遍历所有图元

 YxxfEntBlock blk = D.secEntities.insMSpace.block;

  YxxfEnt ent = null;

 int nextToDraw = 0;

 double minDistance = 999999999;//最小距离

   YxxfEntLine minEnt = null;//最小距离对应的直线

    while (true)

    {

         ent = (YxxfEnt)blk.nextEntity(nextToDraw);

       if (ent == null)

             break;

       if(ent.getClass()==YxxfEntLine.class){

                   YxxfEntLine entLine = (YxxfEntLine)ent;

                   if(entLine.diameter != null){

                          nextToDraw++;

                          continue;

                   }

                //计算直线的斜率 大于1的为纵向的。等于1为45度倾斜,可以认为是横向的。

                   double lfSlope0 = Math.abs(entLine.endpnt.y-entLine.begpnt.y)/Math.abs(entLine.endpnt.x-entLine.begpnt.x);

                   if((xaxisdir.x != 0 && lfSlope0<=1) //文字纵向 直线横向

                          || (xaxisdir.x == 0 && lfSlope0>1)       //文字横向 直线纵向

                          ){

                          nextToDraw++;

                          continue;

                   }

                   //计算距离

                   double distance = PointToSegDist(inspnt.x,inspnt.y,entLine.begpnt.x,entLine.begpnt.y,entLine.endpnt.x,entLine.endpnt.y);

                   if(minDistance>distance){

                          minDistance=distance;

                          minEnt = entLine;

                   }

         }

            nextToDraw++;

    }

if(minEnt!=null)minEnt.diameter = text;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值