irneb 发表于 2022-7-6 09:43:04

镜像中的变换点

今天这件事让我头痛不已。我有一个例程的请求,该例程应该用2x2dsolids“替换”块内的擦除。原因是我们使用了一个带有抹布的门框来“切割”墙壁&图案填充,而实际上不需要修剪。虽然这对技术绘图很有用,但当我们在做演示时,需要对门下的这些白点进行实体填充(就像每个门都有门槛板一样)。
 
所以我想我可以简单地重新定义块,用一个实体替换覆盖。但是不行,因为阴影区域可以有任何颜色,门的两侧可以有两种不同的颜色。我们现在的想法是在每个块参照之外创建两个单独的实体,并将它们发送到门块的正下方。这很好,甚至适用于缩放和/或动态块-但当它们被镜像时,我似乎无法通过简单的编码正确实现。
 
经过多次搜索,我发现了这条线索,但这些线索似乎都没有达到我的目的。目前,我正在使用PeterJamtgart的代码进行转换。因为它在非均匀缩放的块上效果最好,所以它的编码绝对最小。问题是,如果我在镜像块上使用它,实体始终处于关闭状态,就好像该块沿着其插入点的X/Y轴镜像回来一样。
 
我目前(针对Peter的代码)所做的工作是检查XEffectiveScaleFactor的值是否小于0.0(即,查看它是否镜像)。如果是这样,我将围绕Y轴为该块创建一个临时镜像,从该镜像生成点,并使用负Z法线的变换来“反镜像”该点。不幸的是,这使得每个blockreference有4个临时块(因为我想得到4点)。我知道我可以把它全部打包在一个撤销组中,但我觉得它很凌乱。有人知道我怎么摆脱这些临时障碍吗?要么通过来回变换原始数据,要么最好只是通过计算而不影响块?请参见cadtips页面中的修改后的lisp。
 
一定有一些arb的事情,我现在根本无法理解。也许我只是变老了?真丢脸。。。我没想到我已经过山了!

irneb 发表于 2022-7-6 10:01:50

实际上,现在只需做一个测试,Peter的代码似乎比只使用镜像块还要糟糕。如果块的缩放和旋转不是0.0或180.0度,则点也会关闭。这是我的测试代码:
;****************************************************************************************************
; Written By: Peter Jamtgaard copr 2009
; Function for transforming a point from block object coordinate system to a world coordinate system.
; It handles non uniform scaled blocks
; Syntax:(TranslateWorldToObject <block object> <point in world>)
; Syntax(TranslateObjectToWorld <block object> <point inside block>)
; Returns point in World
;****************************************************************************************************

(defun TranslateObjectToWorld (objBlock         ; Block object
                              lstPointInBlock; Coordinates of point (RELATIVE TO BASE POINT)
                                             ; inside the block
                              /      
                              lstInsertion   ; Insertion Point of Block
                              lstPoint         ; List Point of return translate coordinates
                              lstPointInWorld; Coordinates of point inside the WorldCS
                              sngTheta         ; Rotation angle of Block
                              varReturn      ; Variant return of translate coordinates
                           )
(if (not objDocument)(setq objDocument (vla-get-activedocument
                                        (vlax-get-acad-object))))
(setq lstInsertion    (vlax-get objBlock "insertionpoint")
      sngTheta      (vla-get-rotation objBlock)
      lstPointInBlock (list (* (vla-get-XEffectiveScaleFactor objBlock)
                              (+ (*    (cos sngTheta) (carlstPointInBlock))
                                 (* -1 (sin sngTheta) (cadr lstPointInBlock))))
                           (* (vla-get-YEffectiveScaleFactor objBlock)
                              (+ (*    (sin sngTheta) (carlstPointInBlock))
                                 (*    (cos sngTheta) (cadr lstPointInBlock))))
                           (* (vla-get-ZEffectiveScaleFactor objBlock)
                              (caddr lstPointInBlock)))
      varReturn       (vla-translateCoordinates (vla-get-utility
                                                objDocument)               
                                                (vlax-3d-point lstPointInBlock)
                                                acOCS
                                                acWorld
                                                :vlax-false
                                                (vla-get-normal objBlock))
      lstPointInWorld (mapcar '+ lstInsertion
                                 (vlax-safearray->list (variant-value varReturn)))
)
)

;****************************************************************************************************
; Written By: Peter Jamtgaard copr 2009
; Function for transforming a point from block object coordinate system to a world coordinate system.
; It handles non uniform scaled blocks
; Syntax:(TranslateWorldToObject <block object> <point in world>)
; Syntax(TranslateObjectToWorld <block object> <point inside block>)
; Returns point in World
;****************************************************************************************************

(defun TranslateObjectToWorld1 (objBlock ; Block object
                              lstPointInBlock ; Coordinates of point (RELATIVE TO BASE POINT)
; inside the block
                              / lstInsertion ; Insertion Point of Block
                              lstPoint ; List Point of return translate coordinates
                              lstPointInWorld ; Coordinates of point inside the WorldCS
                              sngTheta ; Rotation angle of Block
                              varReturn ; Variant return of translate coordinates
                              toMirror ; State of mirrored block (by Irn?)
                              )
(if (not objDocument)
   (setq objDocument
          (vla-get-activedocument
            (vlax-get-acad-object)
          )
   )
)
;; By Irn?: Check if block's mirrored & create an "unmirrored" block about the Y axis.
(if (setq toMirror (< (vla-get-XEffectiveScaleFactor objBlock) 0.0))
   (setq objBlock   (vlax-invoke objBlock 'Mirror '(0.0 0.0 0.0) '(0.0 1.0 0.0)))
)

(setq lstInsertion (vlax-get objBlock "insertionpoint")
       sngTheta   (vla-get-rotation objBlock)
       lstPointInBlock (list (* (vla-get-XEffectiveScaleFactor objBlock)
                              (+ (* (cos sngTheta) (car lstPointInBlock))
                                 (* -1 (sin sngTheta) (cadr lstPointInBlock))
                              )
                           )
                           (* (vla-get-YEffectiveScaleFactor objBlock)
                              (+ (* (sin sngTheta) (car lstPointInBlock))
                                 (* (cos sngTheta) (cadr lstPointInBlock))
                              )
                           )
                           (* (vla-get-ZEffectiveScaleFactor objBlock)
                              (caddr lstPointInBlock)
                           )
                     )
       varReturn       (vla-translateCoordinates
                         (vla-get-utility
                           objDocument
                         )
                         (vlax-3d-point lstPointInBlock)
                         acOCS
                         acWorld
                         :vlax-false
                         (vla-get-normal objBlock)
                     )
       lstPointInWorld (mapcar '+
                               lstInsertion
                               (vlax-safearray->list (variant-value varReturn))
                     )
)
;; By Irn?: Check if block was "unmirrored"
(if toMirror
   (progn
   (vla-Delete objBlock) ;Erase the temporary "unmirored" block.
   (trans lstPointInWorld '(0.0 0.0 -1.0) 0) ;Translate the "unmirored" point as mirrored about the Y axis
   )
   lstPointInWorld ;If not mirrored, just send calculated point
)
)


(defun c:Pt2WCS-test (/ ss eo pts pt)
(setq pts '((500.0 0.0 0.0) (0.0 0.0 0.0) (500.0 200.0 0.0)))
(if (and (ssget "_:L" '((0 . "INSERT,*POLY*")))
          (setq ss (vla-get-ActiveSelectionset (vla-get-ActiveDocument (vlax-get-acad-object))))
   )
   (progn
   (vlax-for eo ss
       (if (eq (vla-get-ObjectName eo) "AcDbBlockReference")
         (progn
         (setvar "CECOLOR" "1")
         (command "_.PLINE")
         (foreach pt pts
             (command "_None" (TranslateObjectToWorld eo pt))
         )
         (command "")
         (setvar "CECOLOR" "2")
         (command "_.PLINE")
         (foreach pt pts
             (command "_None" (TranslateObjectToWorld1 eo pt))
         )
         (command "")
         (setvar "CECOLOR" "BYLAYER")
         )
         (vla-Delete eo)
       )
   )
   (vla-Delete ss)
   )
)
(princ)
)命令为Pt2WCS测试。
 
附加的是生成的DWG。我做了一个测试块,上面有一些文字,可以很容易地看到镜像/缩放/旋转的想法。然后,测试代码生成2条多段线。每个都应该从块的右下角到插入点,再到右上角。彼得的代码是用红色绘制的,我修改的代码是用黄色绘制的。
 
对于非镜像块,Peter的近似正确,但旋转块的方向和比例似乎不正确。在镜像街区,距离“英里”。我的mod在非镜像上也做了同样的事情,但至少在镜像上没有更糟。
图纸1.dwg

Lee Mac 发表于 2022-7-6 10:13:41

试试这个Irne:
 
使用测试功能:
 
2主要是根据我的程序在这里、这里和这里开发的。

irneb 发表于 2022-7-6 10:31:24

谢谢李,这似乎很有效。现在,为了弄清楚它实际上做了什么,我知道如何做,而不是简单地重复使用别人的代码!

Lee Mac 发表于 2022-7-6 10:46:02

 
谢谢Irné,很高兴听到
页: [1]
查看完整版本: 镜像中的变换点