Class instance / Python

Hello guys , i have a problem with classes in python , i have this class which has 2 method : 1- create a random point and return it .
2- return the random point that created in method 1
when i create a instance from the class and call both methods , the points are different !!!

if i generate 2 random point in method-1 and return them and in method-2 i create a vector between two points that i created in method-1 and return the vector , and i call both methods from SAME instance of the class , then i have 2 points and a vector that is not between them !!!
how is it possible and what should i do !?!?

Python :

import rhinoscriptsyntax as rs
import random

class point:
    
    def __init__(self,val):
        self.val = val
        
        
    def point1(self):
        
        x = random.uniform(0,5)
        y = random.uniform(0,5)
        p1 = rs.AddPoint(x,y,0)
        return p1
        
    def point2(self):
        p2 = self.point1()
        
        
        return p2



obj = point(3)
a = obj.point1()
b = obj.point2()

If I understand, I would do this way:
b = obj.point2(a)

And
def point2(self, a): p2 = self.point1(a)

Best.

@skysurfer , thanks for your comment , but i dont get what you did , can you explain it more.
what is (( a )) ?

This is my version. Not sure I got what you like to do, but this way the 2 points are related.

1 Like

Hi WinG

What happens is that point2 method calls the point1 method. So a new random point is created.
pseudo code:

def point1 (self)
self.pointA = [x,y,z]

Now to retrieve the point generated you can simply

Point = ClassInstance.pointA

Hope this makes sense I’m on my phone so a little brief.

-Willem

2 Likes

Thank you very much guys , i find out what to do now .
Its seems like if i put a (( self.)) before a variable in a class i can make that variable global for that class , right !?

1 Like

Yes.

1 Like

thank you @Willem , it work very well that way on the code above , but when i try to do that in a more complex class i get this error :

Runtime error (MissingMemberException): optimization instance has no attribute ‘nonPlanarNods’

i do exactly the same thing , i create a list of random points in one method (( self.nonPlanarNods )) and in the other method i call them (( points = self. nonPlanarNods )) and when i run , i get that error :frowning:

Can you post an example of the script that is not working, it’s hard to tell what could be the cause.
It seems there is another issue, maybe your name for the class in in conflict with existing classes.

-Willem

sure , here is my script :

Python:


import rhinoscriptsyntax as rs
import scriptcontext as sc
import ghpythonlib.components as ghcomp
import random
import math




class optimization:
    
    def __init__(self,_srf):
        self.srf = _srf
        
        
    def boundry(self):
        
        domainU = rs.SurfaceDomain(self.srf,0)
        domainV = rs.SurfaceDomain(self.srf,1)
        param1 = (domainU[0] , domainV[0])
        param2 = (domainU[1] , domainV[1])
        
        isoCrv = rs.ExtractIsoCurve(self.srf , param1 , 2)
        for i in range(0,2):
            isoCrv.append(rs.ExtractIsoCurve(self.srf , param2 , i))
        
        boundingBoxPts = rs.BoundingBox(self.srf)
        corners = [boundingBoxPts[0],boundingBoxPts[1],boundingBoxPts[2],boundingBoxPts[3]]
        projectSrf = rs.AddSrfPt(corners)
        
        edge = rs.ProjectCurveToSurface(isoCrv , projectSrf , (0,0,-1))
        boundry = rs.JoinCurves(edge , True)
        boundrySrf = rs.AddPlanarSrf(boundry)
        return (boundrySrf , boundry)
        
        
    def generateNods(self):
        
        self.planarNods = []
        
        bounds = self.boundry()
        boundrySrf = bounds[0]
        
        domainU = rs.SurfaceDomain(boundrySrf, 0)
        domainV = rs.SurfaceDomain(boundrySrf, 1)
        
        def remap(value , sourceStart , sourceEnd , targetStart , targetEnd):
            newValue = (((value - sourceStart) / (sourceEnd - sourceStart)) * (targetEnd - targetStart)) + targetStart
            return newValue
        
        while(len(self.planarNods) < 3):
            u = remap(random.uniform(0,1) , 0 , 1 , domainU[0] , domainU[1])
            v = remap(random.uniform(0,1) , 0 , 1 , domainV[0] , domainV[1])
            nod2D = rs.EvaluateSurface(boundrySrf , u , v)
            boolean = rs.IsPointOnSurface(boundrySrf , nod2D)
            if(boolean is True):
                planarNods.append(nod2D)
                
                self.nonPlanarNods = rs.ProjectPointToSurface(self.planarNods , self.srf , [0,0,1])
                
        nods = (self.nonPlanarNods , self.planarNods)
        
        return nods
        
    def force(self):
        
        distance = []
        forces = []
        
        nonPlanarAgents = self.nonPlanarNods
        planarAgents = self.planarNods
        
        for i in range(len(planarAgents)):
            for j in range(len(planarAgents)):
                dist = rs.Distance(planarAgents[i] , planarAgents[j])
                distance.append(dist)
            sortedDistance = sorted(distance)
            smallestDistance = sortedDistance[1]
            nearestIndex = distance.index(smallestDistance)
            force = rs.VectorCreate(planarAgents[i] , planarAgents[nearestIndex])
            forces.append(force)
            distance = []
        
        return (planarAgents , forces)






obj = optimization(surface)
b = obj.force()
#o = obj.generateNods()
#c = o[1]
a = b[0]
c = b[1]

Hi WinG,

First to paste code encapusualte it like so:

```Python
   #code goes here
```

As for your error, check my comments in the class def excerpt below.
If the boolean is nit True self.nonPlanarNods will never be set.

class optimization:
    #...
def generateNods(self):
    #...
    while(len(self.planarNods) < 3):
        #...
        if(boolean is True):
        # if the boolean is not True self.nonPlanarNods will not be set and as such throws an exception when called
            self.nonPlanarNods =...

   #...

HTH
-Willem

@Willem , i dont get it !! if boolean is not true the loop will continue till boolean set to true three times , isnt it right !?
can you please explain more ? i want my random points to be on the surface , what can i do !?
and i really appreciate your help , thanks.

Hi WinG,

I see now what it might be:

obj = optimization(surface)
b = obj.force()

o = obj.generateNods()

When you call obj.force() inside the class force has the line nonPlanarAgents = self.nonPlanarNods however self.nonPlanarNods is not set only after calling obj.generateNods() as that creates self.nonPlanarNods.

so try this:

obj = optimization(surface)
o = obj.generateNods() # first generate Nods so also self.nonPlanarNods and self.planarNods are created
b = obj.force() # then call force


c = o[1]
a = b[0]
c = b[1]

An alternative would be to let force() inside the class call generateNods so only force() needs to be called once:

#...
def force(self):

   distance = []
   forces = []

   nonPlanarAgents,planarAgents = self.generateNods()

   #...

HTH
-Willem

1 Like

YESSS !! thats it @Willem , it work like a charm now :slight_smile: , thank you very much for your time and help .

1 Like

What is the difference between init and main if you’re writing a class?