0
votes

The aim of my code is to take a 3D object with known internal structure, and generate a 2D cross section based on coordinates in a CSV. It will then draw the cross section with matplotlib. The CSV is converted to a list of lists with the format [X,Y,Z,Identifier]. The only issue is that the objects appear 'spiky', as if the code is not calculating the correct Z values. Please read through my code and help spot any sources of error. Any help is appreciated!

Here is my code:

import matplotlib.pyplot as plt
import matplotlib.patheffects as PE
import csv
import numpy as np
from datetime import date
from shapely.geometry import LineString
    
def det(a, b):
        return a[0] * b[1] - a[1] * b[0]

def line_intersection(line1, line2):
    xdiff = (line1[0][0] - line1[1][0], line2[0][0] - line2[1][0])
    ydiff = (line1[0][1] - line1[1][1], line2[0][1] - line2[1][1])
    div = det(xdiff, ydiff)
    if div == 0:
        return False

    d = (det(*line1), det(*line2))
    x = det(d, xdiff) / div
    y = det(d, ydiff) / div

    return [x, y]

[reads CSV, initializes variables, etc] '''

for i in range(len(OBJ)-1):
    if S[i] != [] and OBJ[i+1] != []:
        x_1 = float(OBJ[i][0])
        y_1 = float(OBJ[i][1])
        x_2 = float(OBJ[i+1][0])
        y_2 = float(OBJ[i+1][1])
        line2 = LineString([(x_1,y_1), (x_2,y_2)])
        L2 = [(x_1,y_1), (x_2,y_2)]
        if line1.intersects(line2) == True:
            r=0
            xpoint = line_intersection(L1,L2)
            xp = np.sqrt(((x1-xpoint[0])**2) + ((y1 - xpoint[1])**2))
            xz1 = np.sqrt(((x_1-x1)**2) + ((y_1 - y1)**2))
            xz2 = np.sqrt(((x_2-x1)**2) + ((y_2 - y1)**2))
            zpoint = line_intersection(LZ1, LZ2)
            zp = zpoint[1] 
            if bool(templis) == True:
                if (SectionLength*0.7) < abs(xp - templis[-1][0]):
                    templis.append([xp] )
                    templis[-1].append(zp)
                    try:
                        templis[-1].extend(OBJ[i][3:])
                    except:
                        pass
                    templis = sorted(templis, key= lambda x: x[0])
                    drawdic[OBJ[i][3]].extend(templis)
                    drawdic[OBJ[i][3]].append([])
                    templis = []
            templis.append([xp] )
            OBJ[i].append('OBJ')
            templis[-1].append(zp)
            try:
                templis[-1].extend(OBJ[i][3:])
            except:
                pass
            if bool(templis) == True:
                if (SectionLength*0.7) < abs(xp - templis[-1][0]):
                    templis.append([xp] )
                    templis[-1].append(zp)
                    try:
                        templis[-1].extend(OBJ[i][3:])
                    except:
                        pass
                    templis = sorted(templis, key= lambda x: x[0])
                    drawdic[OBJ[i][3]].extend(templis)
                    drawdic[OBJ[i][3]].append([])
                    templis = []

    if i == (len(OBJ)-2) :
        templis = sorted(templis, key= lambda x: x[0])
        drawdic[OBJ[i][3]].extend(templis)
        drawdic[OBJ[i][3]].append([])
        templis = []    

       

Here is the output: it should be much smoother Example

LineString is a command from the Shapely library that detects if two lines cross.

The CSV separates different shapes, or sections of shapes with an empty list

somewhat confusing, x1, y1, z1 and x2, y2, z2 are starting and ending coordinates for the cross section, while x_1, y_1 etc. are to do with coordinates within the object.

drawdic is a dictionary of all the objects that need to be drawn, sorted by identifier. SectionLength is the length of the section.

Please let me know of any other areas on improvement as well. thanks!

you could add an example for your CSV file and add the necessary imports to run your code : )Sofia
Unfortunately, it does not look like I can add files yet.Eric Tellier