Need help with my geometry classes (PyMEL)


#1
# === CLASSES ===

# 2D Point
class Point2d(object):

    def __init__(self, u, v):
        """ Create a Point2d object using UV coords
        Example: p = Point2d(1,-2) """
        
        self.u = u
        self.v = v


# 2D Line
class Line2d(object):

    def __init__(self, pointA, pointB):
        """ Create a Line2d object using two Point2d objects
        Example: l = Line2d(pointA, pointB) """
        
        self.pointA = pointA
        self.pointB = pointB


# 2D polygon
class Polygon2d(object):

    def __init__(self, lineList):
        """ Create a Polygon2D object using a list of Line2d objects
        Example: l = Polygon2D(list) """
        
        self.lineList = lineList
        self.pos = len(lineList)


# === CODE ===
incList = [(0.0, 0.1), (0.1, 0.0), (0.5, 0.6), (0.4, 0.6)]

# Create list of Point2d -points
pointList = []
for pair in incList :
    pointList.append(Point2d(pair[0], pair[1]))
        
# print("pointList constructed, it is:")
# print pointList
        
# Create list of Line2d -lines 
lineList = []
counter = 0
while counter <= len(pointList)-1:
    if counter != len(pointList)-1:
        # print("pointList[counter] is")
        # print pointList[counter]
        line = Line2d(pointList[counter], pointList[counter+1])
    else: # Final line (last to first point)        
        line = Line2d(pointList[counter], pointList[0])

    # print("created line %s")%line ## Gives (0.0, 0.1), (0.1, 0.0) on the first run
    lineList.append(line)
    # print("lineList is now") ## Gives [Line2d(Point2d(0.0, 0.0), Point2d(0.1, 0.0))] on the first run
    counter += 1
        
# Create polygon object (Polygon2d)
print("lineList is %s")%lineList
return Polygon2d(lineList) ## ERROR: NOT CREATING POLYS

I´ve been trying to solve this issue where I pass a set off 2d points (incList) to a function that creates a convex hull (as a Polygon2d -object), but end up with a scrambled result.
Weird stuff 1: When printing the pointList (commented out), I get an array of Point2d objects, but if I print pointList[counter] I get just the coordinates!!!
Weird stuff 2: When I print a line, I get two tuples instead of a Line2d -object.
Weird stuff 3: When printing the lineList at the end, the array suddenly contains Line2d -objects, one which has a point in 0.0 0.0

What is wrong here?


#2

lineList is already a list of Line2D objects, but when you pass it to Polygon2D, you try to create Line2D objects from the original Line2D object, which seems wrong?


#3

I’m completely lost tbh.
I created these classes with aid from others a couple months ago, here is that thread:
http://tech-artists.org/forum/showthread.php?5574-Need-help-with-some-simple-2d-geometry-classes

self.lineList = [Line2d(*line) for line in lineList]
…was suggested by another person (to be more flexible). His code on github is no longer available so I can’t exactly go back and look at the complete code - so that door is closed.

Either way, I changed that line to self.lineList = lineList
…and my classes appears to be created in the format I want (below)
Polygon2d(Line2d(Point2d, Point2d), Line2d(Point2d, Point2d), Line2d(Point2d, Point2d), …)

Anyways, I’m getting strange errors in the while loop of my function. I’ve placed a print after the line creation, and a print after the line has been appended to the lineList. The first line being created is this tuple ((0.0, 0.1), (0.1, 0.0)) which is correct - but notice that Maya didn’t say (Point2d(0.0, 0.1), Point2d(0.1, 0.0)). BUT the even stranger thing is that when I try and append that tuple to the list, I get:
[Line2d(Point2d(0.0, 0.0), Point2d(0.1, 0.0))]
…which makes no sense at all to me. Where the heck does that Point2d with coords=origin, come from?

EDIT: Code in the original post has been updated with one new print statement, other comments and an update to init in the Polygon2d -class. Hopefully you can make sense of this.


#4

what do you expect to see when you print an instance of one of your classes?


class Point2d(object):
	def __init__(self, u, v):
		""" Create a Point2d object using UV coords
		Example: p = Point2d(1,-2) """
 
		self.u = u
		self.v = v
 
	def __repr__(self):
		'''returns a string, that when evaulated, re-creates this instance.'''
		return 'Point2d({0}, {1})'.format(self.u, self.v)
 
	@property
	def position(self):
		return (self.u, self.v)
 
 
pointA = Point2d(0.0, 0.0)
pointA
// Result: Point2d(0.0, 0.0) //
 
pointA.position
// Result: (0.0, 0.0) //

If you don’t override the repr method, then you usually see this:


pointA
// Result: <__main__.Point2d object at 0x0000000071A8AC88> //


#5

I took your original script without modifications, added repr methods to Point2d and Line2d, and I get the expected result:


# === CLASSES ===

# 2D Point
class Point2d(object):

    def __init__(self, u, v):
        """ Create a Point2d object using UV coords
        Example: p = Point2d(1,-2) """
        
        self.u = u
        self.v = v
        
    def __repr__(self):
        return "Point2d({p.u},{p.v})".format(p=self)


# 2D Line
class Line2d(object):

    def __init__(self, pointA, pointB):
        """ Create a Line2d object using two Point2d objects
        Example: l = Line2d(pointA, pointB) """
        
        self.pointA = pointA
        self.pointB = pointB
    def __repr__(self):
        return "Line2d({l.pointA},{l.pointB})".format(l=self)


# 2D polygon
class Polygon2d(object):

    def __init__(self, lineList):
        """ Create a Polygon2D object using a list of Line2d objects
        Example: l = Polygon2D(list) """
        
        self.lineList = lineList
        self.pos = len(lineList)


# === CODE ===
incList = [(0.0, 0.1), (0.1, 0.0), (0.5, 0.6), (0.4, 0.6)]

# Create list of Point2d -points
pointList = []
for pair in incList :
    pointList.append(Point2d(pair[0], pair[1]))
        
# print("pointList constructed, it is:")
# print pointList
        
# Create list of Line2d -lines 
lineList = []
counter = 0
while counter <= len(pointList)-1:
    if counter != len(pointList)-1:
        # print("pointList[counter] is")
        # print pointList[counter]
        line = Line2d(pointList[counter], pointList[counter+1])
    else: # Final line (last to first point)        
        line = Line2d(pointList[counter], pointList[0])

    # print("created line %s")%line ## Gives (0.0, 0.1), (0.1, 0.0) on the first run
    lineList.append(line)
    # print("lineList is now") ## Gives [Line2d(Point2d(0.0, 0.0), Point2d(0.1, 0.0))] on the first run
    counter += 1
        
# Create polygon object (Polygon2d)
print("lineList is %s")%lineList
# prints
# lineList is [Line2d(Point2d(0.0,0.1),Point2d(0.1,0.0)), Line2d(Point2d(0.1,0.0),Point2d(0.5,0.6)), Line2d(Point2d(0.5,0.6),Point2d(0.4,0.6)), Line2d(Point2d(0.4,0.6),Point2d(0.0,0.1))]


Could it be you’re running another code than the one you’re editing?


#6

OMG! That was the issue - faulty repr methods in my classes.
Fixing that I was able to fix another major issue further down the line. Thank you so much!