dr.hybride Posted April 23, 2021 Posted April 23, 2021 hello  does anyone knows, if is it possible to 3d rotate a 3d bloc from its base point and the other point of the block ? for sure in LISP.  thank you   Quote
rlx Posted April 23, 2021 Posted April 23, 2021 I dont use 3D for my work but can't you use ALIGN command for this? Should work for 2 & 3D transformations. First point would be block insertionpoint from and 2nd point is whatever point (on the block) you feed to align command , then press enter , et voila...done  Maybe post a picture and someone with more 3D knowledge can give you a more intelligent answer. Quote
lrm Posted April 24, 2021 Posted April 24, 2021 With the rotate3d command (not to be confused with 3drotate) you can specify 2 points to define an axis of rotation at any 3d orientation you wish. Quote
dr.hybride Posted April 25, 2021 Author Posted April 25, 2021 (edited) hello everyone I found that but I want to change the second point which will be defined with the angle, one meter from the first point. Â (defun c:3rtx ( / *error* obj tmppoint) ;3D rotate texts mtexts and blocks aound an axis aligned ;on the x axis, passing by their individual insertion points. ;made by Jef! 2015-12-11. (defun *error* ( msg ) (if (not (member msg '("Function cancelled" "quit / exit abort"))) (princ (strcat "\nError: " msg)) ) (princ) ) (princ "\nSelect objects to rotate") (if (ssget) (progn (vlax-for obj (vla-get-activeselectionset (vla-get-activedocument (vlax-get-acad-object))) (if (or (eq (vla-get-objectname obj) "AcDbMText") (eq (vla-get-objectname obj) "AcDbText") (eq (vla-get-objectname obj) "AcDbBlockReference") ) (progn (vla-Rotate3D obj (vlax-3d-point (setq tmppoint (vlax-get obj 'InsertionPoint))) (vlax-3d-point (mapcar '+ tmppoint '(1 0 0))) (/ pi 2)) (if (and (eq (vla-get-objectname obj) "AcDbBlockReference") (= (vlax-get-property obj 'HasAttributes) :vlax-true) ) (vl-cmdf "_.AttSync" "Name" (vla-get-name obj)) ) ) ) ) ) (princ "nothing selected") ) (princ) ) Â Â Â Edited April 25, 2021 by CADTutor Moved code to code block Quote
lrm Posted April 25, 2021 Posted April 25, 2021 Quote I found that but I want to change the second point which will be defined with the angle, one meter from the first point. If you are working in 3D you will need to specify two angles to define the location of the second point. For example, an angle in the XY plane and an angle about the z axis. The distance is not important as the two points are defining an axis of rotation and it doesn't matter how far apart they are. It's not clear what you are trying to do. Your first post indicated that you want to rotate a block in 3D space but your last post seems to imply that you really just want to rotate in a plane. 1 Quote
dr.hybride Posted April 26, 2021 Author Posted April 26, 2021 Sorry i was not clear, i agree with you, i know that to rotate ( 3Drotate and not rotate 3d ) you need to select two points and define an angle, but the thing is i have a lot of block so i dont want to select for each block two points. the idea is that i wanted to use formula trigonometry ( cosinus angle something like this) to select automatically the second point. see the picture Quote
lrm Posted April 26, 2021 Posted April 26, 2021 It is still not clear to me what is your goal. Perhaps someone else would like to jump in and help.  Could you clarify the following? 1. Do you want a vlisp program that will allow you to select many blocks at one time and have them all rotate to some specified orientation or do you want to work on a single block? 2. Do you realize that the angle specified in the Properties panel is the angle of rotation in the WCS and does not reflect the current UCS nor the fact the the block may be rotated out of the WCS XY plane? 3. If you want to rotate an object so that it is oriented from a base point to a reference point you can use the Reference option with the rotate command. For example,  the block MyBox is oriented at an angle of 30°. Let's say we would like the long side of the box to point from the base point to the point at right. Give the rotate command, select the block and then the base point. Now input R (reference) and specify the base point (1) and a second point (2) for the reference direction and a point for the new direction (3).  The result is the following.  Is this what you want to do?   Quote
dr.hybride Posted April 26, 2021 Author Posted April 26, 2021 thank you for your help lrm  yes i want to select many block at one time and rotate at 90°   Quote
lrm Posted April 26, 2021 Posted April 26, 2021 The following command rot90x, will rotate a block by 90° about its x axis but will only do one at a time. Perhaps someone else can enhance it for multiple blocks or has another approach. (defun c:rot90x (/) ; rotates a block by 90° about its x axis. (setq blk (cdr (nentsel)) xdir (nth 0 (nth 1 blk)) basept (nth 3 (nth 1 blk)) refpt (mapcar '+ basept xdir) ) (command "_rotate3d" basept "" "2" basept refpt 90.0) (princ) )  Quote
rlx Posted April 26, 2021 Posted April 26, 2021 (edited) untested but assuming Irm's code works I hope this also works : [code] Â (defun t1 ( / ss i blk xdir basept refpt) Â (if (setq ss (ssget '((0 . "INSERT")))) Â Â Â (repeat (setq i (sslength ss)) Â Â Â Â Â (setq blk (ssname ss (setq i (1- i)))) Â Â Â Â Â (setq xdir (nth 0 (nth 1 blk)) basept (nth 3 (nth 1 blk)) refpt (mapcar '+ basept xdir)) Â Â Â Â Â (command "_rotate3d" basept "" "2" basept refpt 90.0) Â Â Â ) Â ) Â (princ (strcat "\nRotated " (if ss (itoa (sslength ss)) "0") " blocks")) Â (princ) ) Â [/code] Â Edited April 26, 2021 by rlx has [code] tags changed? Quote
lrm Posted April 26, 2021 Posted April 26, 2021 @rlx, mine works for one block, yours does not for multiple blocks.  Error "; error: bad argument type: consp <Entity name: 238f0cb2930>" with: (setq xdir (nth 0 (nth 1 blk)) basept (nth 3 (nth 1 blk)) refpt (mapcar '+ basept xdir))  I'm not sure what you are trying to do with xdir. It's the direction vector of the x axis in WCS of the block. The challenge is going on to the next object in a selection set. It's not clear to me how, or if, you can do that with nentsel. blk via nentsel contains the block's transformation matrix. blk via ssget in your program is just the entity name. Quote
CADTutor Posted April 26, 2021 Posted April 26, 2021 1 hour ago, rlx said: has [code] tags changed? Â Yes, I'm afraid so. The new forum software no longer supports BBcode. It's now considered a legacy feature. However, the editor code blocks work in the same way as before. Quote
rlx Posted April 26, 2021 Posted April 26, 2021 @lrm , ah , yes I see what you mean , hence the untested , didn't take into account entsel returns matrix , probably have to replace this with retrieve inspoint for each block with nentselp or get matrix from block itself. Will have to look at this later because has been very long day for me / very short night.  @david , ok , understood , will use editor code blocks from now on  Quote
dr.hybride Posted April 27, 2021 Author Posted April 27, 2021 Hello evryone thank you all  but it does not work. i tested and see the result in the picture   Quote
rlx Posted April 27, 2021 Posted April 27, 2021 maybe like this (stolen & adapted from master Lee) Â ;;; https://www.cadtutor.net/forum/topic/50653-rotate3d-lisp-need-help/ (defun c:3drblk ( / ang axs idx lst obj sel ) (setq ang (/ pi 2.0)) (if (setq sel (ssget "_:L" '((0 . "INSERT")))) (progn (repeat (setq idx (sslength sel)) (setq lst (cons (cons (setq obj (vlax-ename->vla-object (ssname sel (setq idx (1- idx))))) (vlax-get obj 'insertionpoint) ) lst ) ) ) (princ "\nRotate about [X/Y/Z] <Exit>: ") (while (setq axs (cdr (assoc (grread nil 10) '( ((2 120) 1.0 0.0 0.0) ((2 088) 1.0 0.0 0.0) ((2 121) 0.0 1.0 0.0) ((2 089) 0.0 1.0 0.0) ((2 122) 0.0 0.0 1.0) ((2 090) 0.0 0.0 1.0) ) ) ) ) (foreach itm lst (vlax-invoke (car itm) 'rotate3d (cdr itm) (mapcar '+ (cdr itm) axs) ang) ) ) ) ) (princ) ) Â Quote
lrm Posted April 27, 2021 Posted April 27, 2021 @dr.hybrideplease post a copy of the block you are using. Quote
lrm Posted April 27, 2021 Posted April 27, 2021 @rlx The program 3drblk appears to rotate the blocks about an axis parallel to the world x, y, or z axis. I think the OP wants the blocks to rotated about the block's local axis but he hasn't made that clear. He may in fact may want to define a local axis with 2 points. Having a copy of the block would help to understand the requirements. Quote
rlx Posted April 27, 2021 Posted April 27, 2021  @lrm , you maybe right , only tested it on a flog of flat-world symbols because I have no 3D symbols. They all fell over at the x-axis so was kinda hoping this is it... awell it was worth a shot. Just not experiece with 3D I'm afraid  I was about to experiment with this when I saw Lee's code , hoping I could retrieve entmatrix for each item in selectionset and then feed this to your command. But I guess , beeing somewhat of a resident of flat-world , better leave this to the inhabitants of 3D-world  ; Transpose a matrix Doug Wilson (defun trp ( m ) (apply 'mapcar (cons 'list m))) ; Apply a transformation matrix to a vector by Vladimir Nesterovsky (defun mxm ( m n ) ((lambda ( a ) (mapcar '(lambda ( r ) (mxv a r)) m)) (trp n))) ; Multiply two matrices by Vladimir Nesterovsky (defun mxv ( m v ) (mapcar '(lambda ( r ) (apply '+ (mapcar '* r v))) m)) ; RefGeom (gile) ; test : (setq pl (RefGeom (car (entsel)))) only blocks? (defun RefGeom ( ename / elst ang norm mat ) (setq elst (entget ename) ang (cdr (assoc 50 elst)) norm (cdr (assoc 210 elst))) (list (setq mat (mxm (mapcar '(lambda ( v ) (trans v 0 norm t)) '((1.0 0.0 0.0)(0.0 1.0 0.0)(0.0 0.0 1.0))) (mxm (list (list (cos ang) (- (sin ang)) 0.0) (list (sin ang) (cos ang) 0.0) '(0.0 0.0 1.0)) (list (list (cdr (assoc 41 elst)) 0.0 0.0) (list 0.0 (cdr (assoc 42 elst)) 0.0) (list 0.0 0.0 (cdr (assoc 43 elst))))))) (mapcar '- (trans (cdr (assoc 10 elst)) norm 0) (mxv mat (cdr (assoc 10 (tblsearch "BLOCK" (cdr (assoc 2 elst))))))) ) ) ; https://forums.autodesk.com/t5/visual-lisp-autolisp-and-general/get-entities-inside-a-block/td-p/2644829 ; Entmatrix returns a list which first item is the 3X3 tranformation matrix and second item the insertion point ; of a block refernce in its owner (space or block definition) (defun EntMatrix ( ename / e a n) (setq e (entget ename) a (cdr (assoc 50 e)) n (cdr (assoc 210 e))) (list (mxm (mapcar (function (lambda (v) (trans v 0 n T))) '((1.0 0.0 0.0) (0.0 1.0 0.0) (0.0 0.0 1.0))) (mxm (list (list (cos a) (- (sin a)) 0.0) (list (sin a) (cos a) 0.0) '(0.0 0.0 1.0)) (list (list (cdr (assoc 41 e)) 0.0 0.0) (list 0.0 (cdr (assoc 42 e)) 0.0) (list 0.0 0.0 (cdr (assoc 43 e)))))) (trans (cdr (assoc 10 e)) n 0)))  Quote
dr.hybride Posted April 28, 2021 Author Posted April 28, 2021 (edited) hello everyone thank you all i'm more confortable in VBA, this why i did in VBA , if someone can to translate in lisp.  Public Sub Rotate3D_Exp() Dim ent As AcadEntity Dim vPt As Variant On Error Resume Next ' Get the object to rotate ThisDrawing.Utility.GetEntity ent, vPt, vbLf + "Select the block to rotate: " ' Make sure an object was selected If Err = 0 Then ' Check to see if the selected object was a block reference If ent.ObjectName = "AcDbBlockReference" Then Dim blkRef As AcadBlockReference Set blkRef = ent ' Check to see if the block reference was an instance of the MYBLOCK definition If blkRef.EffectiveName = "Portique shematique" Then ' Define the rotation axis Dim rotatePt1(0 To 2) As Double Dim rotatePt2 As Variant Dim rotateAngle As Double anglebloc = blkRef.Rotation 'anglebloc = blkRef.Rotation * 3.141592 / 180 'rotatePt1 = -3: rotatePt1(1) = 4: rotatePt1(2) = 0 rotatePt1(0) = blkRef.InsertionPoint(0) rotatePt1(1) = blkRef.InsertionPoint(1) rotatePt1(2) = blkRef.InsertionPoint(2) rotatePt2 = ThisDrawing.Utility.PolarPoint(blkRef.InsertionPoint, anglebloc, 1) rotateAngle = 90 rotateAngle = rotateAngle * 3.141592 / 180# ' Rotate the block reference blkRef.Rotate3D rotatePt1, rotatePt2, rotateAngle End If End If End If End Sub   Edited April 28, 2021 by CADTutor Moved code to code block Quote
lrm Posted April 28, 2021 Posted April 28, 2021 It looks like your VBA code rotates the block by 90° about an axis defined by a line from the basepoint to a point define by the the angle of the block. As noted earlier, the angle parameter is the angle defined by the projection of the x-axis of the block onto the xy plane.  Here are two versions of a vlisp program to rotate a block by 90° about an axis define by two points.  rot90x rotates a block by 90° about the x axis of the block. rot90ang rotates a block by 90° about the line define by the x axis of the block projected to the XY plane. This should be similar to your VBA program.  (defun c:rot90x (/ blk xdir basept refpt) ; rotates a block by 90° about its x axis. (setq blk (cdr (nentsel))) (if (= (length blk) 1) (princ "\nError, object not a block.") (progn (setq xdir (nth 0 (nth 1 blk)) basept (nth 3 (nth 1 blk)) refpt (mapcar '+ basept xdir) ) (command "_rotate3d" basept "" "2" basept "_non" refpt 90.0) ) ) (princ) ) (defun c:rot90ang (/ blk xdir basept refpt) ; rotates a block by 90° about its x axis prject to the WCS xy plane. (setq blk (cdr (nentsel))) (if (= (length blk) 1) (princ "\nError, object not a block.") (progn (setq xdir (nth 0 (nth 1 blk)) basept (nth 3 (nth 1 blk)) refpt (mapcar '+ basept xdir) refpt (list (nth 0 refpt) (nth 1 refpt) (nth 2 basept)) ) (command "_rotate3d" basept "" "2" basept "_non" refpt 90.0) ) ) (princ) )  rotate block in 3D.lsp Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.