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!