0

I want automatically create some pairs based on the data stored as numpy arrays. In fact, the numbers in my first arrays are numbers of some lines. I want to connect the lines and create surfaces using created pairs. This is the array of lines:

line_no= np.arange (17, 25)

These lines are in two perpendicular directions. I uploaded a fig to show it (they are as blue and red colors). I know where the direction of my lines change and call it as sep.

sep=20

Another data which should be useable is the number of points creating lines. I call it rep.

rep = np.array([3,3,1])

Then, I used the following code to achieve my goal but it is not correct:

start =line_no[0]
N_x = len(rep) - 1
N_y = max(rep) - 1
grid = np.zeros((N_y + 1, N_x + 1, 2))
kxs = [0] + [min(rep[i], rep[i+1]) for i in range(len(rep)-1)]
T_x = sum(kxs)
T_y = sum(rep) - len(rep)
T_total = T_x + T_y
lines = np.arange(start, start+T_total)
lines_before = 0
for i in range(N_x):
    for j in range(N_y, -1, -1):
        if j >= kxs[i+1]:
            continue
        grid[j,i,0] = lines[lines_before]
        lines_before += 1
for i in range(N_x+1):
    for j in range(N_y-1, -1, -1):
        if j < rep[i] - 1:
            grid[j,i,1] = lines[lines_before]
            lines_before += 1
joints=np.array([])
for i in range(N_x - 1):
    for j in range(N_y - 1):
        square = np.append(grid[j:j+2, i, 0], grid[j, i:i+2, 1])
        if all(square):
            new_joints = square
            joints=np.append (new_joints,joints)

In my fig I have two scenarios: A (rep = np.array([3,3,1])) and B (rep = np.array([1,3,3])). For A I want to have the following pairs:

17, 21, 18, 23
18, 22, 19, 24

And for B:

18, 21, 19, 23
19, 22, 20, 24

In reality the distribution of my lines can change. For example, in scenario A, the last line is not creating any surface and in B the first one is not in any surface and in case I may have several lines that are not part of any surface. For example I may have another red line bellow line number 21 which do not make any surface. Thanks for paying attention to my problem. I do appreciate any help in advance.

enter image description here

A more complicated case is also shown in the following. In scenario C I have:

line_no= np.arange (17, 42)
sep=29
rep = np.array([5,4,4,2,2,1])

In scenario D I have:

line_no= np.arange (17, 33)
sep=24
rep = np.array([1,3,4,4])

enter image description here

1 Answer 1

1

Sorry, but I couldn't go through your implementation. Tip for next time onwards- please try to comment your code, it helps.

Anyway, here is somewhat of a readable implementation that gets the job done. But, I advice you to check with more scenarios to verify the scripts validity before making any conclusions.

import numpy as np

line_no = np.arange(17, 25)
sep = 20  # this information is redundant for the problem
nodes = np.array(np.array([1,3,4,4]))

# for generalised implementation hlines start from 0 and vlines start where hlines end
# offset parameter can be used to change the origin or start number of hlines and hence changed the vlines also
offset = 17

# calculate the number of horizontal lines and vertical lines in sequence
hlines = np.array([min(a, b) for a, b in zip(nodes[:-1], nodes[1:])])
# vlines = np.array([max(a, b) - 1 for a, b in zip(nodes[:-1], nodes[1:])])
vlines = nodes - 1

print(f"hlines: {hlines}, vlines: {vlines}")
# nodes = np.array([3, 3, 1]) ---> hlines: [3, 1], vlines: [2, 2]
# nodes = np.array([1, 3, 3]) ---> hlines: [1, 3], vlines: [2, 2]

hlines_no = list(range(sum(hlines)))
vlines_no = list(range(sum(hlines), sum(hlines)+sum(vlines)))

print(f"hlines numbers: {hlines_no}, vlines numbers: {vlines_no}")
# nodes = np.array([3, 3, 1]) ---> hlines numbers: [0, 1, 2, 3], vlines numbers: [4, 5, 6, 7]
# nodes = np.array([1, 3, 3]) ---> hlines numbers: [0, 1, 2, 3], vlines numbers: [4, 5, 6, 7]

cells = []  # to store complete cell tuples
hidx = 0    # to keep track of horizontal lines index
vidx = 0    # to keep track of vertical lines index
previous_cells = 0
current_cells = 0

for LN, RN in zip(nodes[:-1], nodes[1:]):
    # if either the left or right side nodes is equal to 1, implies only 1 horizontal line exists
    # and the horizontal index is updated
    if LN == 1 or RN == 1:
        hidx += 1
    else:
        # to handle just a blank vertical line
        if LN - RN == 1:
            vidx += 1
        # iterate 'cell' number of times
        # number of cells are always 1 less than the minimum of left and right side nodes
        current_cells = min(LN, RN)-1
        if previous_cells != 0 and previous_cells > current_cells:
            vidx += previous_cells - current_cells
        for C in range(current_cells):
            cell = (offset + hlines_no[hidx],
                    offset + vlines_no[vidx],
                    offset + hlines_no[hidx+1],
                    offset + vlines_no[vidx+current_cells])
            hidx += 1
            vidx += 1
            cells.append(cell)
        # skip the last horizontal line in a column
        hidx += 1
        previous_cells = min(LN, RN)-1

print(cells)

Results

# nodes = np.array([3, 3, 1]) ---> [(17, 21, 18, 23), (18, 22, 19, 24)]

# nodes = np.array([1, 3, 3]) ---> [(18, 21, 19, 23), (19, 22, 20, 24)]

# nodes = np.array([5,4,4,2,2,1]) ---> [(17, 31, 18, 34), 
#                                       (18, 32, 19, 35), 
#                                       (19, 33, 20, 36), 
#                                       (21, 34, 22, 37), 
#                                       (22, 35, 23, 38), 
#                                       (23, 36, 24, 39), 
#                                       (25, 39, 26, 40), 
#                                       (27, 40, 28, 41)]

# nodes = np.array([1,3,4,4]) ---> [(18, 25, 19, 27), 
#                                   (19, 26, 20, 28), 
#                                   (21, 27, 22, 30), 
#                                   (22, 28, 23, 31), 
#                                   (23, 29, 24, 32)]

Edit: Updated the code to account for the special case scenarios

Sign up to request clarification or add additional context in comments.

9 Comments

Dear @sai, I do appreciate your solution. Sorry for my late feedback. At the time I was not in front of my desktop and I could not check it. I have just two issues. When I add another line in scenario A bellow the 21, and nodes = np.array([4, 3, 1]), I do not have correct result. And also in reality surfaces do not create on column, they create a grid. For example, in scenario A you can think that there are also two other surfaces in the right hand side of existing two ones: line_no=np.arange(17, 31), sep=23 and nodes = np.array([4, 4, 2, 1]). Thanks for being that much supportive.
Can you add(pictures) other edge case scenarios that the script should satisfy? More information would help me and anyone else on SO to get a complete picture and provide a complete solution.
Dear @sai, I updated my post to show what I want. In advance, I appreciate any contribution.
Dear @sai. I really do appreciate your help. The pooint is that for other cases I am facing errors. For example, let say in scenario D, I remove the first horizontal line (number 17). Then I will have line_no = np.arange(18, 25), sep = 24 and nodes = np.array(np.array([3,4,4])) and still I should have the same surfaces but I face a error : IndexError: list index out of range
Try with vlines = nodes - 1
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.