Is there a direct method to do that? Or do I have to calculate the transform to get it from where it is to where I want it?
So far I’ve been deleting the instance and recreating it, but that means a new GUID.
Thanks,
Jim
Is there a direct method to do that? Or do I have to calculate the transform to get it from where it is to where I want it?
So far I’ve been deleting the instance and recreating it, but that means a new GUID.
Thanks,
Jim
I’m not very familiar with instances, but I think you should be able to do something along the lines of the following:
get the InstanceDefinition
from the doc.InstanceDefinitions list
instance = doc.InstanceDefinitions.Find(<GUID>)
get the list of InstanceObjects
that the definition has
references = instance.GetReferences()
(each reference object can have a different transform)
set the new transform and commit the changes to the object
references[0].InstanceXform = myNewTransform
references[0].CommitChanges()
(what always confuses me is the difference between the block/instance definition and the actual block/instance objects)
I was hoping I could do something like that but the property is read-only.
Ah, ok.
For “normal” objects, this works:
doc.TransformObject(obj, myNewTrannsform, true)
see http://4.rhino3d.com/5/rhinocommon/html/M_Rhino_DocObjects_Tables_ObjectTable_Transform_1.htm
Hopefully for InstanceObjects it works too, in that it updates the InstanceXform.
Heh, you would think that would work, I’m trying it now (after guessing what I need to do to the transforms to get the “difference” between them) and it’s saying Transform takes 4 arguments not 3…which it doesn’t. EDIT. I did fix that, still just trying to figure out exactly how to multiply the matrices together to get the transform I want…EDIT…which is still kickng my butt.
I’m baffled, if I delete the curve and redraw it, it works fine, if I figure out the rotation between the current position and where I want it to end up (in a brute-force manner of making vectors about the origin and transforming and getting the rotation transform between them) and Transform the instance, there is some sort of error in the transform, the instances go flying off into space, but all my testing so far(again by comparing vectors) to see if the block gets transformed right seems to indicate it does.
Hi Jim
If I understand correctly the problem, rs.XformInverse() can help here.
This test script transforms the source instance into the target instance.
To get the transformation from the source instance to the target instance
it inverts the source instance transform and multiplies it by the target instance transform …
if that makes sense …
import rhinoscriptsyntax as rs
def main():
id0 = rs.GetObject( 'Source instance ?' )
if not id0:
return
xf0 = rs.BlockInstanceXform( id0 )
id1 = rs.GetObject( 'Target instance ?' )
if not id1:
return
xf1 = rs.BlockInstanceXform( id1 )
xfi = rs.XformInverse( xf0 )
xfo = rs.XformMultiply( xf1, xfi )
id2 = rs.TransformObject( id0, xfo )
main()
Cheers
Thanks, I am trying to do basically that, though all in RhinoCommon, but it’s just sending everything into space. I know the transform I’m trying to do is correct, since if I just delete and recreate the instance it’s fine. That said…as a plan B…is it possible(since this is how everything works internally anyway) to delete the instance and make a new one, assigning it the same GUID? There seem to be “replace” methods for most kinds of geometry but not instances…
I tried to write the test in RhinoCommon
Does this work ?
import Rhino
def main():
result, obref0 = Rhino.Input.RhinoGet.GetOneObject(
'Source instance ?', True, Rhino.DocObjects.ObjectType.InstanceReference )
if result != Rhino.Commands.Result.Success:
return
inst0 = obref0.Geometry()
xf0 = inst0.Xform
Rhino.RhinoDoc.ActiveDoc.Objects.UnselectAll()
Rhino.RhinoDoc.ActiveDoc.Views.Redraw()
result, obref1 = Rhino.Input.RhinoGet.GetOneObject(
'Target instance ?', True, Rhino.DocObjects.ObjectType.InstanceReference )
if result != Rhino.Commands.Result.Success:
return
inst1 = obref1.Geometry()
xf1 = inst1.Xform
ok, xfi = xf0.TryGetInverse()
if not ok:
return
xfo = xf1 * xfi
Rhino.RhinoDoc.ActiveDoc.Objects.Transform( obref0, xfo, True )
Rhino.RhinoDoc.ActiveDoc.Views.Redraw()
main()
And … yes, I looked for a way to replace a block instance too … but found nothing …
Cheers
It seems funny there isn’t a specific method…maybe omitting such niceties helps to keep blocks “light.”
I’m not sure which details weren’t quite right in my version but modeling it after your example did finally get it to work, thanks.
…Another somewhat related question…how would I in RhinoCommon do the equivalent of ReplaceBlock?
I’m trying to rewrite this as a rhino script to integrate into a larger script that already exists. But I’m having trouble translating python to rhinoscript. Im using ObjectByLayer as opposed to prompting for the input.
Clearly I’m stumped and missing some fundamental logic. Here is what i have so far. Any ideas/help is appreciated.
Rhino.UnselectAllObjects
arrTarget = Rhino.ObjectsByLayer("Target", True)
arrSelected = Rhino.SelectedObjects
If IsArray(arrSelected) Then
arrTargetXform = Rhino.BlockInstanceXform(strObject)
If IsArray(arrTargetXform) Then
Rhino.UnselectAllObjects
arrSource = Rhino.ObjectsByLayer("Source", True)
arrSelected = Rhino.SelectedObjects
arrSourceXform = Rhino.BlockInstanceXform(strObject)
Rhino.TransformObject strObject, Rhino.XformInverse(arrTargetXform)
End If
End If
Another attempt.
It keep getting an error “Type mismatch in parameter. String required” when I use the Rhino.BlockInstanceXform(strObject)
Rhino.UnselectAllObjects
arrSource = Rhino.ObjectsByLayer("Source", True)
arrSourcexform = Rhino.BlockInstanceXform(strObject)
Rhino.UnselectAllObjects
arrTarget = Rhino.ObjectsByLayer("Target", True)
arrTargetxform = Rhino.BlockInstanceXform(strObject)
arrResult = Rhino.XformInverse(arrSourceXform)
arrMover = arrTargetxform * arrResult
Rhino.TransformObject arrSource, arrMover, True
Where is strObject defined ?
I cannot see where it comes from …
I see what you’re your saying. I’m not a developer, so I make rookie mistakes Here is another attempt. Now it throws a “type mismatch” error indicated in the script below. I appreciate the help!
arrObjects = Rhino.ObjectsByType(4 + 8 + 16 + 32 + 4096, True)
If Not IsArray(arrObjects) Then Exit Sub
For Each strObject In arrObjects
If IsArray(arrObjects) Then
If Rhino.IsBlockInstance(strObject) Then
Rhino.UnselectAllObjects
arrSource = Rhino.ObjectsByLayer("Source", True)
arrXform = Rhino.BlockInstanceXform(strObject)
Rhino.UnselectAllObjects
arrTarget = Rhino.ObjectsByLayer("Target", True)
arrTargetXform = Rhino.BlockInstanceXform(strObject)
arrResult = Rhino.XformInverse(arrXform)
`'This is the line that errors.`
arrMove = arrXform * arrResult
Rhino.TransformObject arrSource, arrMove, True
End If
End If
Next
I think you can’t multiply two transforms with ‘*’ in Rhinoscript (you can in Python).
Maybe try arrMove=Rhino.XformMultiply (arrXform, arrResult)
But why are you multiplying a transform with its inverse?
lol, I don’t know. I was trying to deconstruct the python script in the thread above.
I’m trying to replace the Target with the Source while using the transform, scale, rotation properties of the Target. Swap blocks.
rhino.command replaceblock works great but I can’t figure out how to bypass the manual inputs via a script.
I found the python example above. Got it to work for my needs, but now i need to embed it into a much larger script that is already written in rhino.script. So I was attempting to deconstruct the python example and translate it into rhino script.
ok, now it runs the script successfully without errors, but the result appears to place all the blocks that are stored in the block manager at 0,0,0. the blocks have not been scaled.
arrObjects = Rhino.ObjectsByType(4 + 8 + 16 + 32 + 4096, True)
If Not IsArray(arrObjects) Then Exit Sub
For Each strObject In arrObjects
If IsArray(arrObjects) Then
If Rhino.IsBlockInstance(strObject) Then
' Rhino.Command "-Purge "
'Center
Rhino.UnselectAllObjects
arrSource = Rhino.ObjectsByLayer("Source", True)
arrSelected = Rhino.SelectedObjects
If IsArray(arrSelected) Then
arrXform = Rhino.BlockInstanceXform(strObject)
End If
Rhino.UnselectAllObjects
arrTarget = Rhino.ObjectsByLayer("Target", True)
arrSelected = Rhino.SelectedObjects
If IsArray(arrSelected) Then
arrTargetXform = Rhino.BlockInstanceXform(strObject)
End If
Rhino.TransformObject strObject, Rhino.XformInverse(arrTargetXform), True
End If
End If
Next
I tried to translate the first script I posted into VBS.
Here it is.
It seems to work here …
sub main
id0 = rhino.GetObject( "Source instance ?" )
if isnull( id0 ) then exit sub
xf0 = rhino.BlockInstanceXform( id0 )
id1 = rhino.GetObject( "Target instance ?" )
if isnull( id1 ) then exit sub
xf1 = rhino.BlockInstanceXform( id1 )
xfi = rhino.XformInverse( xf0 )
xfo = rhino.XformMultiply( xf1, xfi )
id2 = rhino.TransformObject( id0, xfo )
end sub
main
HTH
Thanks so much for your help. I really appreciate the time you’ve taken to help me.
I remain confused as to why I’m having so much trouble converting this to work within another script. If I use it as-is, it works perfectly! As soon as I try to automate the selection for the Source and Target I get errors like str required. This was the first approach that gives the error ‘Type mismatch in parameter. String required.’
If I change the selection method (first two lines) I get the error
'id0 = rhino.GetObject("Source instance ?") CHANGE TO
id0 = Rhino.ObjectsByLayer("Source", True)
If isnull(id0) Then Exit Sub
xf0 = rhino.BlockInstanceXform(id0)
id1 = rhino.GetObject("Target instance ?")
If isnull(id1) Then Exit Sub
xf1 = rhino.BlockInstanceXform(id1)
xfi = rhino.XformInverse(xf0)
xfo = rhino.XformMultiply(xf1, xfi)
id2 = rhino.TransformObject(id0, xfo)
So I attempted to move some things around and change the code structure to match the larger scripts structure. The selection portion appears to work now, but when I try to do the Xform Multiply I get an error that says ‘Type mismatch in parameter. Array required.’
I’m stumped and in over my head.
Rhino.UnselectAllObjects
arrSource = Rhino.ObjectsByLayer("Source", True)
arrSXform = Rhino.BlockInstanceXform
arrSXformInv = Rhino.XformInverse
Rhino.UnselectAllObjects
arrTarget = Rhino.ObjectsByLayer("Target", True)
arrTXform = Rhino.BlockInstanceXform
'This is where the error occurs
arrDiff = Rhino.XformMultiply(arrTXform, arrSXformInv)
arrMove = rhino.TransformObject(arrSource, arrMath)