Source code for prosi3d.preprocessing.utils

import pandas as pd

[docs]def point_in_polygon(polygon, point): """ Raycasting Algorithm to find out whether a point is in a given polygon. Performs the even-odd-rule Algorithm to find out whether a point is in a given polygon. This runs in O(n) where n is the number of edges of the polygon. * :param polygon: an array representation of the polygon where polygon[i][0] is the x Value of the i-th point and polygon[i][1] is the y Value. :param point: an array representation of the point where point[0] is its x Value and point[1] is its y Value :return: whether the point is in the polygon (not on the edge, just turn < into <= and > into >= for that) """ # A point is in a polygon if a line from the point to infinity crosses the polygon an odd number of times odd = False # For each edge (In this case for each point of the polygon and the previous one) i = 0 j = len(polygon) - 1 cnt = 0 while i < len(polygon) - 1: i = i + 1 # If a line from the point into infinity crosses this edge # One point needs to be above, one below our y coordinate # ...and the edge doesn't cross our Y corrdinate before our x coordinate (but between our x coordinate and infinity) if (((polygon[i][1] > point[1]) != (polygon[j][1] > point[1])) and (point[0] < ( (polygon[j][0] - polygon[i][0]) * (point[1] - polygon[i][1]) / (polygon[j][1] - polygon[i][1])) + polygon[i][0])): # Invert odd odd = not odd cnt =+ 1 j = i # If the number of crossings was odd, the point is in the polygon return odd, cnt
[docs]def getPnts(fname, pnts=4): ''' Works at the moment only with ''' f = open(fname, "r", encoding='UTF-8') #Point(X = 121.836, Y = 42.2803, Z = 1.36) list_x = [] list_y = [] i = 0 for line in f: line = line.replace('\n','') x0 = line.find('X = ') + 4 x1 = line.find(',', x0) x = line[x0:x1] y0 = line.find('Y = ') + 4 y1 = line.find(',', y0) y = line[y0:y1] list_x.append(float(x)) list_y.append(float(y)) # read only first 4 points i += 1 if i >= pnts: break # append first point to close polygon list_x.append(list_x[0]) list_y.append(list_y[0]) #d = {'x': list_x, 'y': list_y} df = pd.DataFrame() df['x'] = list_x df['y'] = list_y # points are not ordered in polygon representation (they are sorted by x and y) return df
[docs]def getPolygons(path, partlist): path = path + '\\stl\\' #files = filesInFolder_simple(path, typ='txt') polygonlist = [] for part in partlist: txtfile = path + part.rsplit('.', 1)[0] + '.txt' polygon = shapePolygon(txtfile) polygonlist.append(polygon) return polygonlist
[docs]def shapePolygon(fname): ''' iterative sorting by nearest next point to create a polygon with points in the right row. does not work for star-shaped areas -> then better use alphashape or sth else for sorting. ''' pnts = getPnts(fname) # last point equals first point because of getPnts() to create a closed polygon idxlst = [] df = pnts[1:-1].copy() for i in range(1, len(pnts) - 1, 1): # dataframe for distance calculation # nearest point is next point df.loc[:,'dx'] = df['x'] - pnts.loc[i-1, 'x'] df.loc[:,'dy'] = df['y'] - pnts.loc[i-1, 'y'] df['dx2'] = df['dx'].pow(2) df['dy2'] = df['dy'].pow(2) # distance from row in original list to df['dis'] = df[['dx2','dy2']].sum(axis=1).pow(1./2) #print(df['dis'].loc[df['dis'] == df['dis'].min()]) foundidx = int(df.loc[df['dis'] == df['dis'].min()].index.values) idxlst.append(foundidx) df.drop(foundidx, inplace=True) idxlst = [0] + idxlst + [len(pnts) - 1] #apply index pnts.index = idxlst pnts.sort_index(inplace=True) polygon = [] for row in pnts.itertuples(): polygon.append((row.x, row.y)) return polygon
[docs]def getZ(fname): ''' Returns layer numbers of first layer above all binding errors of one stltxt file ''' f = open(fname, "r", encoding='UTF-8') #Point(X = 121.836, Y = 42.2803, Z = 1.36) list_z = [] i = 0 for line in f: i += 1 # dont read first 4 points if i <= 4: continue # delete line break line = line.replace('\n','') # find z coordinate z0 = line.find('Z = ') + 4 z1 = line.find(')', z0) z = line[z0:z1] #floating number does not allow exact filtering -> use integers list_z.append(int(float(z)*1000)) list_z = list(dict.fromkeys(list_z)) list_z.sort() df = pd.DataFrame() df['z'] = list_z df['dz'] = df['z'].diff() cnts = df.dz.value_counts() # two values dominate (gap distance between error end to start and wise versa start to end). shorter distance is typically to the end of the error / missing layers zgaps = list((cnts.index[0], cnts.index[1])) zgaps = [int(item) for item in zgaps] zgaps.sort() # layer numbers of first layer above error z = list(df['z'].loc[df['dz'] == zgaps[0]].values/80) z = [int(item) for item in z] return z
[docs]def setcolor(expType): ''' defines colors regarding eos exposureType number. called by function pfeile(). Args: expType ''' switch={ # hatch 0:'dodgerblue', # Ansicht Bauteilaußenkante EOSprint # dunkler -> downskin, heller -> upskin 1:'seagreen', # down 2:'mediumspringgreen', # in 3:'springgreen', # up # contour 4:'darkviolet', # down 5:'mediumorchid', # in 6:'magenta', # up 10:'violet', # edge 7:'orangered', # support 8:'dodgerblue', # jump 9:'darkorange', 11:'darkorange' } return switch.get(expType, 'black')
[docs]def chk_ascending(pandas_series): if ~pandas_series.is_monotonic: df = pd.DataFrame() df['diff1'] = pandas_series.diff() print(f"Not ascending cum_sums: {df.loc[pandas_series.diff() < 0].shape[0]}") print(f'Monotonic: {pandas_series.is_monotonic}')
[docs]def class_objects_to_dataframe(welds_updated): ''' Helper function to convert list of objects to a 2d-representaion (pandas dataframe) using all attributes as columns and object as line. Args: list of objects Returns: pandas dataframe ''' # create Dataframe from welds_updated objects cols = list(welds_updated[0].__dict__.keys()) #cols = cols.append('duration_ms()') df = pd.DataFrame() for col in cols: df[col] = [getattr(weld, col) for weld in welds_updated] # additional values via methods # use t1 for temporal length and convert later to end time df['t1'] = [weld.duration_ms()/1000 for weld in welds_updated] # delete dropped short welds (ttlid == -1) df.drop(df.loc[df.ttlid == -1].index, inplace=True) return df