Python Forum
How do you work with procedurally generated data?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How do you work with procedurally generated data?
#1
I want to write a script that generates a list of (X,Y) coordinates to be passed into CAD software in order to automate some extremely repetitive geometry-related tasks. I am learning python on my own as my first OOP language. I have no formal background in engineering or computer programming. I used to be pretty good with BASIC back in the MSDOS days, but I've never worked with any of the modern languages. I'm doing ok so far, but I have run into an issue where I need to generate some objects, the number of which is defined by the user. I need a hierarchical data structure in which data can be individually recalled later by a naming convention that can be programmed - an array of sorts. My first instinct was to have variables created in a FOR loop that would generate sequential names, such as var1, var2, etc. but upon my research it seems that this practice is not only frowned upon, but also requires some hacky low-level coding like using vars(), which can be problematic in some situations.

Here is an example of what I am trying to do:
The user is asked to input height, width, and qty of rectangles (boxes). The script generates (X,Y) coordinates for a row of equally sized and equally spaced boxes. Later in the code, I want to be able to refer to specific boxes for further processing. The way it is written currently, if I need to refer to a specific point I can do something like print(Box1.A.X) to get the X coordinate of the bottom left corner of the first rectangle. I need to be able to reference the data at all levels of the hierarchy. In other words I need to be able to call an individual box as a list of(A,B,C,D), individual point as a list of (X,Y), or an individual X or Y as an integer.

This is how I have gone about it so far:
I created a class called Point and gave it attributes self.X and self.Y. When an instance is created, the X and Y values are fed in as arguments. I then created a new class called Box. This object has 2 arguments for the X/Y values of the bottom-left point (A). Then, 4 instances of the Point class are created starting with Point A and adding the height and width to the X and Y values to get B,C, and D. Now, I can create a rectangle easily using something like Box1=Box(3,2). This makes a rectangle with the bottom-left point at (3,2). Then if I need to refer to a specific point I can do something like print(Box1.A.X) to get the X coordinate of the bottom left corner of the first rectangle. What I need now is to be able to reference the data at all levels of the hierarchy, in other words I need to be able to call an individual box as a list of (A,B,C,D), individual point as a list of (X,Y), or an individual X or Y as an integer.

This is where I'm stumped. I want to generate 'n' number of boxes, but every way I've tried to create the name of the new boxes has failed. I can programatically generate a string with the name I want, but apparently strings can't be used for variable names.

I also tried generating a nested dictionary, such that each point object yields a dictionary with keys X and Y, each box object yields a dictionary with keys for points ABCD, and then have a master dictionary with keys for each individual box. When I tried it though, I was able to generate key names for the coordinates and points, but not for the boxes. What is the convention for organizing an array of data like this?

For reference, here is a sample of my code:
#USER DEFINED VARIABLES (I just put in some simple defaults for sake of this example)
box_qty = 4    
box_spacing = 1
box_height = 3
box_width = 6

class Point:
	"""Object containing X-Y coordinates of a single point"""
	def __init__(self,x,y):
		self.X = x
		self.Y = y

	def __str__(self):
		return self.__dict__

class Box:
	"""Creates a rectangle and assigns 4 points, ABCD, to it relative to point A"""
	def __init__(self,x,y):
		self.A = Point(x,y)
		self.B = Point(x, y + box_height)
		self.C = Point(x + box_width, y + box_height)
		self.D = Point(x + box_width, y)
		
	def __str__(self):
		return f'A:{self.A}\nB:{self.B}\nC:{self.C}\nD:{self.D}'
# Now, I need something like this, but written in such a way that actually works Big Grin
start = Point(0,0)
for i in range(box_qty):
	f'Box{i}' = Box(start.X,start.Y)
	start.X += (box_width + box_spacing)

# ...so that I can write a function such as:
def get_box(box_name,point_name,x_or_y):
	~some code that parses the name of a specific point

get_box(Box1,C,X)
>>>6
Reply
#2
(Jul-08-2020, 02:26 AM)rbbauer00 Wrote: I need to be able to reference the data at all levels of the hierarchy. In other words I need to be able to call an individual box as a list of(A,B,C,D), individual point as a list of (X,Y), or an individual X or Y as an integer.

I don't really understand what you mean by this. Perhaps I'm getting hung up on the term "hierarchy", when I don't see a hierarchy here. Also, why do you need to do this? Is there another way to work with the boxes that maybe makes more sense?

Quote:I can programatically generate a string with the name I want, but apparently strings can't be used for variable names.

Correct, because strings are values and you can't assign to values. If you want to store a collection of items, then yeah, use a collection (e.g. list, tuple, set or dictionary).

Quote:# Now, I need something like this, but written in such a way that actually works Big Grin
start = Point(0,0)
for i in range(box_qty):
	f'Box{i}' = Box(start.X,start.Y)
	start.X += (box_width + box_spacing)

# ...so that I can write a function such as:
def get_box(box_name,point_name,x_or_y):
	~some code that parses the name of a specific point

get_box(Box1,C,X)
>>>6

You've provided something that looks much like a test, which is a good thing. However, I'm a bit confused. The function is called get_box but returns an integer, rather than a Box. I assume what you want this function to do is get the value of Box1.C.X,but I'm not sure how where the value 6 comes from. Ignoring the problems in the code and just going through the for loop as if it worked, I get 13 using the code in the previous example.

One way to do something like that could be to use attrgetter from the operator module (official docs are here, but obviously seek other sources if this isn't clear):

>>> import operator
>>> class Foo(object):
...     def __init__(self):
...             self.bar = 1
...             self.baz = 4
... 
>>> foo = Foo()
>>> get_bar = operator.attrgetter("bar")
>>> get_bar(foo)
1
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  How to copy work sheet data one workbook to other? sayyedkamran 2 691 Nov-03-2023, 09:10 AM
Last Post: Larz60+
  HOW TO USE C# GENERATED DLL davide_vergnani 2 1,632 Jun-12-2023, 03:35 PM
Last Post: davide_vergnani
  Formating generated .data file to XML malcoverc 3 1,348 Apr-14-2022, 09:41 PM
Last Post: malcoverc
  how to work with SendGrid data aayushi98 0 1,295 Jan-26-2021, 10:31 AM
Last Post: aayushi98
  upload image with generated code from Postman does not work magic7598 0 1,681 Nov-30-2019, 10:32 AM
Last Post: magic7598

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020