How to copy a Vector3d in Python?

python

#1

Hello!
Is there a simpler way to copy a Vector3D than like so?
There’s no Copy() or Set() method in Vector3D.

import Rhino.Geometry as rg

va = rg.Vector3d(1,2,3)
vb = rg.Vector3d(0,0,0)

vb.X = va.X
vb.Y = va.Y
vb.Z = va.Z
vb *= 10

print va
print vb

Thanks!
Best regards
Eugen


#2

Hi Eugen, this works:

vb = rg.Vector3d(va)

Jess


#3

Hi Jess, thanks!!

But doesn’t this create a new vector in memory that overwrites the old one?
The idea is to keep the object vb and just ‘load’ it with different values.

My code is not really performance or memory critical (some mesh primitive), but I want to maintain a good style.


#4

It creates a new vector (copy of va, not referencing it). I think this is what you want.


#5

Vector vb already exists, and should ideally just be set to different values. That’s different than creating it anew.


#6

I think that that was what you already did:

vb.X = va.X
vb.Y = va.Y
vb.Z = va.Z

// Rolf


#7

Yes, if the vector were a simple list you could use python’s slicing, but that does not work with vector objects.
Here a bit more info: http://www.python-course.eu/deep_copy.php

Edit: btw vb *= 10 also creates a new Vector3d just in case :wink:


#8

Jess is right

No, vb is just a name that you bind to the new vector created by

rg.Vector3d( va )

this is called a copy-constructor in other languages

That is: it creates a new object ( a Vector3d here ) taking the needed data from another (different, independent) Vector3d.

This in Python is written:

vb = va

( But what already exists in not a Vector3d, just a name … or a variable if you prefer )

HTH, regards

EDIT

Now I realize that there might have been some misunderstanding here …
What Jess wrote REPLACES all this code

you have not to create a vector in vb before copying …

vb = rg.Vector3d( va )

also does that … and then copies va’s values into it

Does this make sense ?


#9

Hi emilio,

The sample Eugen posted was a bit misleading. I think the question actually is:
What’s the preferred way to “assign” a copy of a vector to an existing Vector3D variable?

Since I’m working on the same stuff at the moment I made a performance test. Looks like the method I’ve posted (initializing a new Vector3d) is twice as fast than maintaining the vector and assigning new coordinates separately. I don’t see a difference in the memory resources.

Of course, if this vector has been referenced further, then the values have to be assigned separately to not loose the reference.

Jess


#10

Hi Jess

Ah, OK.
Thanks for clarifying …
Reading Eugen’s code, I thought that he needed a new copy of the vector … but was wrong … :blush:

Regards


#11

Hi guys! Thanks for all the replies!
Ok, this seems to work (odd, thought I tried this…)

import Rhino.Geometry as rg

va = rg.Vector3d(1,2,3)
vb = rg.Vector3d(0,0,0) # could be omitted
vb = va
vb *= 10

print va # 1,2,3
print vb # 10,20,30

I’m still somewhat used to JScript from my Softimage SDK times… Python is different, I notice.
This line in JScript (and C, C++)
vb = va
means, both variables will point to the same object in memory then, and the result would be
10,20,30
10,20,30
For copying a vector in JScript, I have to write
vb.Copy(va)
… which does not exist here.

What I want to avoid is uselessly creating tons of vectors, when I could ‘recycle’ existing one inside some calculation loop. Saves time and memory (if that really makes a difference in my little project is another story. I just like the style).
Still, I’m not sure with
vb = rg.Vector3d(0,0,0)
vb = va
Is vb re-created in line 2, or is it really ‘loaded’ with the values from va?

Cheers!
Best regards
Eugen


(Nathan 'jesterKing' Letwory) #12

Regarding assignment and references you may want to read through

and


#13

Hi Eugen,

In this case vb is not a new object. But if later on you do this:
vb *= 10 then it will become a new Vector3d object.
See vc in this example (HTH):

import Rhino.Geometry as rg

va = rg.Vector3d(1,2,3)
vb = rg.Vector3d(va)
vc = vb

vb.X = 10

print "va =", va 
print "vb =", vb 
print "vc =", vc

vb *= 10 

print "va =", va 
print "vb =", vb 
print "vc =", vc

(Tom) #14

Hello just in addition:

Vector3d is a Struct not a Class, so in VB or C# its copied already by setting it equal (vecA = vecB).
However, due to Pythons everything is an object rule, this does not work for Python, and as Jess said you need to write vecA = rg.Vector3d(vecB) in order to copy, or by setting the coordinates equal


(Tom) #15

https://docs.microsoft.com/en-us/dotnet/standard/design-guidelines/choosing-between-class-and-struct
https://www.codeproject.com/Articles/728836/Using-struct-and-class-whats-that-all-about

… structs are under certain situations ways faster, because they are allocated on the stack and not on the heap. So although being copied, they will perform better as being pass by “reference” and placed on the heap like classes( If certain rules are omitted.) By the way you don’t reference floats or ints very much…See structs(Vector3d etc.) more as a combo of simple data-types. How does this helps you in Python?I don’t know! But if you think of optimisation: Find the real bottleneck - the algorithm. Microtuning is often very micro. And obvious optimisation is not always optimisation -> Referencing is not always faster as passing by Value.


#16

Thanks everyone!
I just learned about

import this

=)

Looks like the whole ‘by reference’ or ‘by value’ thinking is of not much use here. I will go and try to learn the proper Python ways…
… and contemplate about why

va *= 10

or

va = rg.Vector3d.Multiply(va, 10)

create a new vector va, but

va.X*=10
va.Y*=10
va.Z*=10

mutates the vector.

[correction]
In my code I will do it the simple way and just use what Jess suggested:
vb = rg.Vector3d(va)
to copy a vector.

Best regards
Eugen


#17

Hi Eugen,

to find out if two different objects point to the same in memory using python you might use the id method. eg:

print id(va)
print id(vb)

if both ids are indentical, you did not make a copy.

_
c.


#18

Good tip, thanks!