gmajvfhpa 发表于 2018-5-10 16:03:21

有懂lisp编程的吗?一个用C写的求圆心程序帮忙改写成用lisp

在写AtuoCAD插件已知圆弧起点,终点,和凸度,求圆心的程序。原来用C写的,现在想改成lisp写。
/********************************************************************   
   file base:main
   file ext:    cpp
   author:      scenic
   purpose:   由起点和终点以及凸度求圆弧的圆心
*********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define PI 3.141593
#define RESOLUTION 0.000001
typedef struct point
{
   double x;
   double y;
   double z;
}Point,*PPoint;
typedef struct arc   
{
   double sx;
   double sy;
   double sz;
   double ex;
   double ey;
   double ez;
   double r;
   double cx;
   double cy;
   double cz;
   double startangle;
   double endangle;
}ARC,*PARC;
int getArcR(Point startpoint ,Point endpoint ,double bulge,PARC parc);//圆弧起始点和终止点 和凸度
int getArcR(Point startpoint ,Point endpoint ,double bulge,PARC parc)
{   
    double x1(0.0),y1(0.0),x2(0.0),y2(0.0),arcangle(0.0);//圆弧起始点和终止点, 以及所包的角度
    x1=startpoint.x;
    y1=startpoint.y;
    x2=endpoint.x;
    y2=endpoint.y;
    parc->sx=startpoint.x;
    parc->sy=startpoint.y;
    parc->sz=0.0;
    parc->ex=endpoint.x;
    parc->ey=endpoint.y;
    parc->ez=0.0;
    arcangle=4*atan(fabs(bulge));   //弧包含的弧度
    printf("arcangle= %f \n",arcangle*180/PI);
    if((-RESOLUTION<arcangle)&&(arcangle<RESOLUTION))
    {
      printf("LINE (x1= %f,y1=%f) (x2=%f,y2=%f) \n",x1,y1,x2,y2);
      return 1;
    }
    double chordlength;       //弦长
    chordlength=sqrt(pow((x1-x2),2)+pow((y1-y2),2));
    doubleradius;         //圆弧半径
    radius=(0.5*chordlength)/(sin(0.5*arcangle));
    printf("r= %f\n",radius);
    if((-RESOLUTION<(radius))&&((radius)<RESOLUTION))
    {
      printf("startpoint can't be same as endpoint \n");
      return 1;
    }
    //--------------已知圆上两点和半径,求圆心坐标--------------------
    double verticalinterval;//圆心到弦垂距
    verticalinterval=sqrt( radius* radius-chordlength*chordlength/4);
    double cx,cy;//圆心坐标
    double midx,midy; //起始点和终止点连线的中点横纵坐标
    midx=0.5*(x1+x2);
    midy=0.5*(y1+y2);
    if((-RESOLUTION<(bulge-1))&&((bulge-1)<RESOLUTION))
    {
         printf("arc: (x=%f y=%f r=%f ) \n",midx,midy, radius);
         parc->cx=midx;
         parc->cy=midy;
         parc->cz=0.0;
         parc->r=radius;
         printf("x=%lf,y=%lf,z=%lf r=%f\n",parc->cx,parc->cy,parc->cz,parc->r);
         return 1;
   }
    //printf("mid=%f   mid=%f \n",midx,midy);
//--------------------------------------------------------------------
    //弦矢量的方向角(0-2PI之)
    double chordangle=0;//起点到终点的弦向量与x正方向之间的倾斜角
    chordangle=acos((x2-x1)/sqrt(pow(x2-x1,2)+pow(y2-y1,2)));
    printf("chordangle =%f \n",chordangle);
    double amass; //弦向量与X轴正向单位向量的叉积= (y2-y1)k
    amass = y2-y1;//由(由(x2-x1)*0-1*(y2-y1))得到
    if (amass<0)
   {   
         chordangle=2*PI-chordangle;
         //printf("here \n");
   }
    printf("chordangle =%f \n",chordangle*180/PI);
//---------------------------------------------------------------
    double DirectionAngle=0.0;//弦中点到圆心的直线向量的方向角(0-2PI之间)
    if ((bulge>0 && arcangle<PI)||(bulge<0 && arcangle>PI))
   {
         DirectionAngle=chordangle+PI/2;
   }
    if((bulge<0 && arcangle<PI)||(bulge>0 && arcangle>PI))
   {
         DirectionAngle=chordangle-PI/2;
   }
    if(DirectionAngle<0)
    {
         DirectionAngle=DirectionAngle+2*PI;
    }
    if (DirectionAngle>2*PI)
   {
         DirectionAngle= DirectionAngle-2*PI;
   }
//---------------------------------------------------------------
    double d;//圆心到弦的距离
    d=sqrt( radius* radius-chordlength*chordlength/4);
    printf("DirectionAngle=%f,chordangle=%f\n",DirectionAngle*180/PI,chordangle*180/PI);
    if((-RESOLUTION<(DirectionAngle-0))&&((DirectionAngle-0)<RESOLUTION))
   {
         cx=midx+d;
         cy=midy;
         printf("1:cx=%f cy=%f\n ",cx,cy);
   }
    else
if((-RESOLUTION<(DirectionAngle-PI/2))&&((DirectionAngle-PI/2)<RESOLUTION))
   {
         cx=midx;
         cy=midy+d;
         printf("2:cx=%f cy=%f\n ",cx,cy);
   }
    else
if((-RESOLUTION<(DirectionAngle-PI))&&((DirectionAngle-PI)<RESOLUTION))
   {
         cx=midx-d;
         cy=midy;
         printf("3:cx=%f cy=%f\n ",cx,cy);
   }
    else
if((-RESOLUTION<(DirectionAngle-3*PI/2))&&((DirectionAngle-3*PI/2)<RESOLUTION))
   {
         cx=midx;
         cy=midy-d;
         printf("4:cx=%f cy=%f \n ",cx,cy);
   }
    else
{
    double nslope,k;//nslope 为弦的斜率,K为弦中垂线的斜率
    double nAngle;//中垂线的倾斜角;
    double X,Y; //圆心相对于弦中心点的坐标偏移量
    nslope = (y2 - y1) / (x2-x1);
    k = -1 / nslope;
    nAngle = atan(k) ;
    X = fabs(cos(nAngle) * d);
    Y = fabs(sin(nAngle) * d);
    if (DirectionAngle > PI/2 && DirectionAngle < PI )
    {
      X = -X;
      Y = Y;
    }
    if (DirectionAngle > PI && DirectionAngle < (PI+PI/2) )
    {
      X = -X;
      Y = -Y;
         
    }
    if (DirectionAngle > (PI+PI/2)&& DirectionAngle <2*PI)
    {
      X = X;
      Y = -Y;
         
    }
   
    cx=midx + X;
    cy=midy + Y;
    printf("cx=%f cy=%f\n ",cx,cy);
}
    parc->cx=cx;
    parc->cy=cy;
    parc->cz=0.0;
    parc->r=radius;
    printf("x=%lf,y=%lf,z=%lf r=%f \n",parc->cx,parc->cy,parc->cz,parc->r);
         return 1;
}
int getArcAngle(PARC parc)//取得圆弧角度
{
    double sx(0.0),sy(0.0),ex(0.0),ey(0.0),cx(0.0),cy(0.0),r(0.0);//arc 的起点终 点圆心的坐标
    double startangle(0.0),endangle(0.0);
   sx=parc->sx;
   sy=parc->sy;
    ex=parc->ex;
    ey=parc->ey;
    cx=parc->cx;
    cy=parc->cy;
   r=parc->r;
    //
    double num1(0.0),num2(0.0);//x方向矢量和圆心到弧线起点和终点的矢量的叉乘的z 分量
   startangle=acos((sx-cx)/r);
   num1=sy-cy;
   if(num1<0)
   {
         startangle=2*PI-startangle;
   }
   printf("startangle =%f \n",startangle*180/PI);
    endangle=acos((ex-cx)/r);
   num2=ey-cy;
   if(num2<0)
   {
         endangle=2*PI-endangle;
   }
   printf("endangle =%f \n",endangle*180/PI);
   return 0;
}
int main()
{
    Point startpoint={119.523,6.29683,0.0} ;
    Point endpoint={92.3448,16.3001,0.0} ;
    double bulge=-0.607501;
    ARC arc1;//={};
    getArcR(startpoint ,endpoint ,bulge,&arc1);
    getArcAngle(&arc1);
    getchar();
    return 0;
}

gmajvfhpa 发表于 2018-5-10 21:22:57

自已网上找到一个,测试过可用
;;参数 pt = 圆弧起点 np = 圆弧终点 gx = 弓弦比
;;返回表 '(圆心 半径)
(defun get_Center (pt np gx / pa bj xc gg rr cp mdp)
(setq        pa (angle pt np)                ;以弧度为单位返回两点之间连线与当ucs下x轴之间的夹角
        bj (* (atan (abs gx)) 4)        ;反正切值
        xc (* 0.5 (distance pt np))        ;1/2两点间距离
        gg (* gx xc)
)
(if (/= 0.0 gg)
    (progn                                ;
      (setq rr (/ (+ (* xc xc) (* gg gg)) (* 2 gg)))

      (setq cp (polar pt pa xc)                ;求点的指定角度,指定距离的点

          cp (polar cp (+ pa (/ pi 2)) (- rr gg))
      )
      (list cp rr)                        ;组成一个表
    )
    (list pt 0.0)
)
)

bright2307 发表于 2018-11-21 11:50:44

gmajvfhpa 发表于 2018-5-10 21:22
自已网上找到一个,测试过可用

虽然看不懂,但还是觉得很厉害~~~今天突然看见公众号上推得lisp

atommann 发表于 2018-11-21 12:25:20

AutoCAD 可以用 C 做扩展吗?(以前不知道)只知道可以用 VB 和 lisp. 以前也学过一些 AutoCAD 的 Lisp

qiqirachel 发表于 2018-11-21 13:10:03

lisp用来做坐标变换是真的方便

qiqirachel 发表于 2018-11-21 13:10:21

另外lisp语言本身不难,楼主可以自学
页: [1]
查看完整版本: 有懂lisp编程的吗?一个用C写的求圆心程序帮忙改写成用lisp