Link_tester
Link_tester

Reputation: 1081

how to create lines and surfaces using points of a regular grid in Python

I have a bunch of points and want to do some geometrical processes on them. Points create a regular grid including vertical (red) and horizontal (blue) lines (a fig is uploaded). I want to work with the number and also coordinate (x,y,z) of the points. For example, points numbers and coordinate in scenario A of my fig are:

point_no= np.arange (1,9)
point_A_coordinate=np.array([[0,0,2], [0,1,3], [0,2,2], [1,0,1], [1,1,3], [2,0,1], [2,1,1], [3,0,1]]

I have the number of points in each column (I mean the red lines) (shown in red circle in fig). In scenario A it is:

chunk_val_A=np.array([3, 2, 2, 1])

When chunk_val_A[0] is 3, it means I have 2 red lines in that chunk. First one is created by connecting point 1 to 2 and the second line by point 2 to 3. Then, my algorithm should know that point number 3 must not be connected to 4 because chunk_val_A[0] is 3. In next chunk, I start by connecting 4 to 5 and stop at 5 because chunk_val_A[0] + chunk_val_A[1] equals 5. As output I want to have the point numbers that create red line as pairs:

[(1, 2), (2, 3), (4, 5), (6, 7)]

For blue (lines that connect chunks) lines it is a little bit complicated. About number of connecting lines from chunk i to chunk i+1, if the chunk_val array is descending (scenarios A and C), it equals chunk_val_A[i+1], if it is ascending (scenarios B and D) it equals chunk_val_A[i]. But in scenario E I have both ascending and descending and I want to regard the rule until where it is ascending and then change it from where it starts to be descending. I may have some peaks but I want to keep the rule the same as before. To select which pairs create blue lines, if the values of chunk_val[i] and chunk_val[i+1] be the same, just simply pair the first ones of each chunk, then, seconds and so on (like in scenario A I pair point numbers 4-6 and 8-7 to connect the second and third chunks). In other cases (like first and second chunks of all scenarios), I should check the coordinate. In scenario A, second chunk has point less than first one and If I check x and y of points point_A_coordinate[:,0:2], missing point is the last point (it's x and y should be 1 and 2) of the second chunk. So two connecting lines will start from the lower part of the first chunk. In scenario B from first to second chunk, the first one misses the lower point so the only line get connected with upper point of the second chunk. Finally I want to have such pairs for the blue lines of scenario A:

[(1, 4), (2, 5), (4, 6), (5, 7), (6, 8)]

after creating such lines, I want to use them for making surfaces. If the algorithm can make firstly re line and number them and later blue ones, I think it will be possible to find out where these lines can be paired. In scenario A I have shown line numbers in rectangle. I want to have these pairs to create surfaces in scenario A:

[(1, 5, 3, 6), (3, 7, 4, 8)]

As the final issue, I want to extract the number of lines that are close to the dashed red line. In scenario A, they are (I marked them by a cross in all scenarios):

[(2, 6, 8, 4, 9)]

These are the things I want to do in Python. I do appreciate if anyone help me in any step of it. I do appreciate any help for such a long issue. Thanks in advance. I tried the following code for creating lines but it was not successful for all the case (I just used print function to show the pairs):

cord_A=np.array([[0,0,2], [0,1,3], [0,2,2], [1,0,1], [1,1,3], [2,0,1], [2,1,1], [3,0,1]])
cord_B=np.array([[0,2,2], [1,1,3], [1,2,2], [2,1,1], [2,2,3], [3,0,1], [3,1,1], [3,2,1]])
cord_C=np.array([[0,0,2], [0,1,3], [0,2,2], [1,1,1], [1,2,3], [2,1,1], [2,2,1], [3,2,1]])
cord_D=np.array([[0,0,2], [1,0,3], [1,1,2], [2,0,1], [2,1,3], [3,0,1], [3,1,1], [3,2,1]])

chunk_val_A=np.array([3, 2, 2, 1])
chunk_val_C=np.array([3, 2, 2, 1])
chunk_val_B=np.array([1, 2, 2, 3])
chunk_val_D=np.array([1, 2, 2, 3])

cord=np.array([[0,0,2], [0,1,3], [0,2,2], [1,0,1], [1,1,3], [2,0,1], [2,1,1], [3,0,1]]) # each time use one scenario
chunk_val=np.array([3, 2, 2, 1]) # again from the same scenario
summ=np.cumsum(chunk_val)
countinuous_point=np.arange(1,9)
splited_point=np.split(countinuous_point,np.cumsum(chunk_val))[:-1]
for i in countinuous_point:
    if i in summ:
        continue
    print (i, i+1) # it gives red lines
print ('All')
for j in range (len (chunk_val)-1):
    if chunk_val[j]==chunk_val[j+1]:
        for m, n in zip (splited_point[j], splited_point[j+1]):
            print (m, n) # it gives the blue lines when the chunks have the same length
    else:
        if cord[splited_point[j][-1]-1,1] > cord[splited_point[j+1][-1]-1,1]:
            for h, p in zip (splited_point[j], splited_point[j+1]):
                print (h,p) # it gives the blue lines when the chunks are like scenario A
        if cord[splited_point[j][-1],1] > cord[splited_point[j+1][0],1]:
            for h, p in zip (splited_point[j][1:], splited_point[j+1]):
                print (h,p) # it gives the blue lines when the chunks are like scenario B               
        if cord[splited_point[j][0],1] < cord[splited_point[j+1][0],1]:
            for h, p in zip (splited_point[j][1:], splited_point[j+1]):
                print (h,p) # it gives the blue lines when the chunks are like scenario C
        if cord[splited_point[j][-1],1] < cord[splited_point[j+1][-1],1]:
            for h, p in zip (splited_point[j][1:], splited_point[j+1]):
                print (h,p) # it gives the blue lines when the chunks are like scenario D

enter image description here

Upvotes: 1

Views: 304

Answers (1)

wuerfelfreak
wuerfelfreak

Reputation: 2439

This gives would be my solution to extracting the surfaces. I hope this helps you. Did not implement a solution for finding the edges close to the red dashed line though.

import numpy as np

point_no= np.arange (1,9)
point_A_coordinate=np.array([[0,0,2], [0,1,3], [0,2,2], [1,0,1], [1,1,3], [2,0,1], [2,1,1], [3,0,1]])
chunk_val_A=np.array([3, 2, 2, 1])

max_x = max([x for x,y,z in point_A_coordinate])
max_y = max([y for x,y,z in point_A_coordinate])

points = np.full((max_x+1,max_y+1), -1) # Grid for storing points -1 marks that there is no point.
red_lines = []
blue_lines = []
n = 0
for chunk, chunk_val in enumerate(chunk_val_A):
    for i in range(chunk_val):
        points[chunk,i] = 1 # 1 markes that there is a point
        n += 1
        if i > 0 and points[chunk,i-1] >= 0: red_lines.append( ((chunk,i-1), (chunk,i)) ) #adds red lines
        if chunk > 0 and points[chunk-1,i] >= 0: blue_lines.append(((chunk-1, i), (chunk,i))) # adds blue lines

print(points) # contains all your points like you would draw them on the paper. -1=no point . otherwise points z-kordinate
print(red_lines) # contains all red lines but named by there x,y cord-pairs
print(blue_lines) # contains all blue lines but named by there x,y cord-pairs

#surfaces
surfaces = []
for x in range(max_x):
    for y in range(max_y):
        if( points[x,y] >= 0 and # checks if all for points exist
            points[x+1,y] >= 0 and
            points[x,y+1] >= 0 and
            points[x+1,y+1] >= 0):
                surfaces.append((
                    red_lines.index( ((x,y), (x,y+1)) ) +1, # gets the number of each line and adds it to the surface
                    blue_lines.index(((x, y), (x + 1, y))) + len(red_lines) + 1,
                    red_lines.index(((x + 1, y), (x + 1, y + 1))) + 1,
                    blue_lines.index( ((x, y+1), (x+1, y+1))) + len(red_lines) + 1,
                ))

print(surfaces) # contains all surfaces

red_lines_numbers = [red_lines.index( red_line ) +1 for red_line in red_lines] 
blue_lines_numbers = [blue_lines.index( blue_line ) + len(red_lines) +1 for blue_line in blue_lines]

red_lines_points_numbers = [(
        [ i for i,cords in enumerate(point_A_coordinate) if all(cords[:2] == red_line[0])][0]+1,
        [ i for i,cords in enumerate(point_A_coordinate) if all(cords[:2] == red_line[1])][0]+1
    ) for red_line in red_lines]

blue_lines_points_numbers = [(
        [ i for i,cords in enumerate(point_A_coordinate) if all(cords[:2] == blue_line[0])][0]+1,
        [ i for i,cords in enumerate(point_A_coordinate) if all(cords[:2] == blue_line[1])][0]+1
    ) for blue_line in blue_lines]

You really stepped up the numbering-game. Most code is just for handling your complex numbering. I first converted everything to the respective x,y coordinates and back afterwards because it is way more intuitive to do math with.

Upvotes: 2

Related Questions