1

I have some points in 3d, and after connecting them, I have created some lines using them. Now, I have the line numbers are a NumPy array, but I do not know how to join the number of lines.

lines=np.arange (17, 31)

In fact, line numbers of the surfaces are somehow messy. Lines are in two sets, and each set is parallel (blue and red lines in the uploaded fig). I also know two other things: the last number of which direction of line changes (sep) and also the number points of the second set of lines (red ones) (rep).

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

Based on my fig, I have four surfaces created by lines numbered 17-25-18-27, 18-26-19-28, 20-27-21-29 and 21-28-22-30. I created the following code to create such pairs but it was not successful at all:

for i in lines:
        if rep[0]==rep[1]:
            print (i, sep+1, i+1, sep+1)
        elif rep[0]!=rep[1]:
            print (i, sep+1+np.abs (rep[1]-rep[0]), i+1, sep+1+np.abs (rep[1]-rep[0])+ 1 + np.abs (rep[1]-rep[0]))

In fact, I want an algorithm to print the following:

17, 25, 18, 27
18, 26, 19, 28
20, 27, 21, 29
21, 28, 22, 30

I appreciate it if anyone helps me create such an algorithm that can generate pairs of surfaces. In reality, my lines array is bigger. I want to figure out a way to create surfaces based on the rep, sep and lines. In advance, I do appreciate any help. Thanks for devoting time.

enter image description here

1 Answer 1

3

A not-so-fancy way would be to build the grid of lines, and then collect the 4-tuples of lines from the grid.

First, the preamble:

#! /usr/bin/env python3

import numpy as np

start = 17
sep = 23
rep = np.array([4,3,3,1])

To build the grid, note that there the length of rep is how long the grid is in the x axis, and the maximum value in rep is how long it is in the y axis. However, we are building a grid of lines, not points, so it's 1 less in each direction. Note that I use N_y and N_x in that order so that a simple print shows the grid in format that's closer to the diagram in the picture.

N_x = len(rep) - 1
N_y = max(rep) - 1
grid = np.zeros((N_y, N_x, 2))

How many horizontal lines are there in each column? For the column formed by points (x_i, y) and (x_i+1, y), that's min(rep[i], rep[i+1]) - the number of points in the smaller column. For column 0, it's 0 - there's nothing to the left of the grid. That also gets us the total number of horizontal lines.

The number of vertical lines in each column is easy - it's the number of points in the y axis - 1. (And hence the total number of vertical lines is the sum of rep - length of rep.)

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)

Let's start filling the grid. The indexing here is awkward since we're filling it from bottom up, and since the axes are swapped as mentioned earlier. We go from left to right and bottom to top.

# `lines_before` is essentially, an index into the `lines` array,
# keeping track of how many lines have already been used
lines_before = 0
for i in range(N_x):
    for j in range(N_y-1, -1, -1):
        if j >= kxs[i+1]:
            # We haven't reached the minimum depth (or height, however you think of it)
            continue
        grid[j,i,0] = lines[lines_before]
        lines_before += 1
print(grid[:,:,0])

for i in range(N_x):
    for j in range(N_y-1, -1, -1):
        if j < rep[i] - 1:
            grid[j,i,1] = lines[lines_before]
            lines_before += 1
print(grid[:,:,1])

At this point the output is, for the numbers in the question:

[[19. 22. 23.]
 [18. 21.  0.]
 [17. 20.  0.]]
[[26. 28. 30.]
 [25. 27. 29.]
 [24.  0.  0.]]

The line numbers do match with the image, and the zeros now indicate where lines aren't present.

Now we can collect the sets of lines. Starting from the top, and going left to right and top to bottom, at each position we collect the horizontal line there and the one below it, and the vertical line there and the one to the right of it. (From the image, then, that would be taking (19, 18, 26, 28), (18, 17, 25, 27), etc.) For each collected set, if any number is zero, that means it's missing a line, and we can eliminate it. So:

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):
            print(square)

Giving:

[19. 18. 26. 28.]
[18. 17. 25. 27.]
[22. 21. 28. 30.]
[21. 20. 27. 29.]

It's not in the order you want, and we're building the grid, which might be too expensive, but I leave the ordering and optimization as an exercise, with the following notes:

  1. From kxs and rep, the number of the line at each position in the grid can be determined, so we don't need the grid at all.
  2. The ordering is just a question of which direction you traverse the grid.
Sign up to request clarification or add additional context in comments.

4 Comments

In that case the grids are bigger in different directions for x and y. So grid itself will be np.zeros((N_y + 1, N_x + 1, 2)), and in the loops, the loop for x will have for j in range(N_y, -1, -1) and the loop for y will have for i in range(N_x+1), which give the output of [20. 19. 22. 24.] and [19. 18. 21. 23.].
Dear @muru, Thanks for being that much helpful. Is there any was to mix both of them? I mean lets say sep=25, and rep = np.array([4,3,1,1,4,4]). Then, I should have five surfaces.
Don't you get 5 sets of lines using the modifications in my last comment?
Unfortunately no, it gives me two first surfaces which are not correct.

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.