lockmyeye 发表于 2004-1-3 13:17:00

[原创][LISP]根据允许偏离距离DIST_MIN,处理LWPOLYLINE的凸度数据(弧段)

本帖最后由 作者 于 2004-1-11 2:25:26 编辑

程序代码内容
;;;根据允许偏离距离DIST_MIN,处理LWPOLYLINE的凸度数据(弧段)。
;;;由凸度计算出弧段直径,再计算以允许偏离距离DIST_MIN为弓高的弧段弦长度LENGTH_XIAN_MAX
;;;再由弧长LENGTH_XIAN和最大弦LENGTH_XIAN_MAX计算要插入顶点数NUM_HU,然后插入顶点
;;;90项点数
;;;42弧段弓弦比=(/ 弓高 (/ 弦长 2.0))
(DEFUN lwpolyline_remove42 (ss1          dist_min
                            /            curve-obj
                            data_new   diameter
                            dist_min   dxfold_10
                            dxfold_42    ename
                            length_gonglength_hu
                            length_hu_max
                            length_start length_xian
                            num1         num_hu
                            point_add_num
                            ss1          tmp
                           )
    ;;检查参数
    (IF (NOT ss1)
      (SETQ ss1 (SSADD))
    )
    (IF (OR (/= 'pickset (TYPE ss1)) (AND (/= 'real (TYPE dist_min)) (/= 'int (TYPE dist_min))))
      (*error* "参数类型错。")
    )
    (PRINC (STRCAT "\n\t0\t处理含有凸度的LWPOLYLINE,共< " (ITOA (SSLENGTH ss1)) " >。"))
    (SETQ num1 0)
    (REPEAT (SSLENGTH ss1)
      (SETQ ename         (SSNAME ss1 num1)
            curve-obj   (VLAX-ENAME->VLA-OBJECT ename)
            num1          (1+ num1)
            data_new      (LIST)                ;更新后的数据
            dxfold_10   nil                   ;上一个顶点坐标
            point_add_num 0                     ;插入的顶点数
      )
      (PRINC (STRCAT "\r\t" (ITOA num1)))
      (FOREACH data_one (ENTGET ename)
            (COND ((= 10 (CAR data_one))
                   (IF (AND dxfold_10 (/= dxfold_42 0.0)) ;如果是弧片断
                     (PROGN ;;42弧段弓弦比=(/ 弓高 (/ 弦长 2.0))
                              ;;直径=(/ (+ (* 弦长 弦长 0.25) (* 弓高 弓高) 弓高))
                              (SETQ length_xian (DISTANCE (CDR data_one) dxfold_10) ;弦长
                                    length_gong (ABS (* dxfold_42 length_xian 0.5)) ;弓高
                                    diameter    (/ (+ (* length_xian length_xian 0.25) (* length_gong length_gong)) length_gong)
                                                ;直径
                              )
                              ;;反算最大弦长LENGTH_XIAN_MAX
                              ;;弦长=(SQRT (* (- (* 直径 弓高) (* 弓高 弓高)) 4))
                              ;;计算出分段数目NUM_HU
                              (SETQ length_hu_max (SQRT (ABS (* (- (* diameter dist_min) (* dist_min dist_min)) 4)))
                                    length_start(VLAX-CURVE-GETDISTATPOINT curve-obj dxfold_10)
                                    length_hu   (ABS (- (VLAX-CURVE-GETDISTATPOINT curve-obj (CDR data_one)) length_start))
                              )
                              (IF (< length_hu_max dist_min)
                                  (SETQ num_hu 0)
                                  (SETQ num_hu      (FIX (/ length_hu length_hu_max))
                                        length_hu_max (/ length_hu (1+ num_hu))
                                  )
                              )
                              ;;插入NUM_HU个顶点
                              (REPEAT num_hu
                                  (SETQ length_start(+ length_start length_hu_max)
                                        point_add_num (1+ point_add_num)
                                  )
                                  (IF (SETQ tmp (VLAX-CURVE-GETPOINTATDIST curve-obj length_start))
                                    (SETQ data_new (APPEND data_new (LIST (CONS 10 (MAPCAR '* '(1 1) tmp)))))
                                  )
                              )
                     )
                   )
                   (SETQ dxfold_10 (CDR data_one))
                  )
                  ((= 42 (CAR data_one))
                   (SETQ dxfold_42 (CDR data_one)
                         data_one'(42 . 0.0)
                   )
                  )
            )
            (SETQ data_new (APPEND data_new (LIST data_one)))
      )
      ;;更新顶点数
      (SETQ data_new (SUBST (CONS 90 (+ point_add_num (CDR (ASSOC '90 data_new)))) (ASSOC '90 data_new) data_new))
      (IF (NOT (ENTMOD data_new))
            (*error* "不能更新实体数据。")
      )
    )
    (PRINC)
)
;;;测试
(DEFUN c:test ()
    ;;根据允许偏离距离DIST_MIN,处理LWPOLYLINE的凸度数据
    (WHILE (SETQ tmp (SSGET "X" '((0 . "LWPOLYLINE") (-4 . "/=") (42 . 0.0))))
      (lwpolyline_remove42 tmp 0.05)
    )
    (PRINC)
)
(PRINC)

无痕 发表于 2004-1-3 20:19:00

人家简化还来不及,你却要加点。不知道你用在什么方面?

lockmyeye 发表于 2004-1-4 01:46:00

输出为外部文件,转换成不支持ARC的系统。
我是为了输出成e00文件进行处理的。

aeo000000 发表于 2004-1-10 15:57:00

本帖最后由 作者 于 2004-1-10 17:40:46 编辑

;;;gg-->原来的凸度
(setq ang (* 4 (atan (abs gg))) ;;;-->这弧线的包含角
;;;dist_min -->你给的允许偏离距离:新凸度
(setq ang_new(* 4 (atan (abs dist_min))) ;;;-->新角度
那么新弧线长为:
(setq new_hu_len(* old_hu_len(/ ang_new ang))) ;;;old_hu_len求应该很方便,就是你的"length_hu"

现在关键是你的dist_min 是根据什么来的.
能不能讲讲

lockmyeye 发表于 2004-1-11 02:22:00

我是用来把大比例尺地形图的线输出成E00文件的。方案中有限差,最大不能超过图中距离0.1毫米,DWG数据用的是实地坐标,比例尺.1:1000。就是说不可以超出0.1。实际上为了保险起见,我把它调到0.05了。
页: [1]
查看完整版本: [原创][LISP]根据允许偏离距离DIST_MIN,处理LWPOLYLINE的凸度数据(弧段)