def intersection_of_plane_with_slice(slice_index, plane): """ ASSUMING AXIAL ORIENTATION, finds the line that repreents the interection between the two planes IN 2D Parameters ---------- slice_index : int the z index of the axial slice. plane : sympy Plane object The plane of interest. Returns ------- sympy Line2D object. """ # set up the plane of the slice flat_plane = sp.Plane((1, 0, slice_index), (-1, 0, slice_index), (0, 1, slice_index)) inter = plane.intersection(flat_plane)[0] intersection_2d = sp.Line((inter.p1[0], inter.p1[1]), (inter.p2[0], inter.p2[1])) return intersection_2d
def _check_intersection(self, ray0, ray1, tri0, tri1, tri2): from pascal3d.utils.geometry import intersect3d_ray_triangle n_rays = len(ray0) assert len(ray1) == n_rays assert len(tri0) == n_rays assert len(tri1) == n_rays assert len(tri2) == n_rays l1 = sympy.Line3D(sympy.Point3D(*ray0.tolist()), sympy.Point3D(*ray1.tolist())) p1 = sympy.Plane(sympy.Point3D(*tri0.tolist()), sympy.Point3D(*tri1.tolist()), sympy.Point3D(*tri2.tolist())) t1 = sympy.Triangle(sympy.Point3D(*tri0.tolist()), sympy.Point3D(*tri1.tolist()), sympy.Point3D(*tri2.tolist())) i1 = p1.intersection(l1) if len(i1) == 0: ret1 = False else: ret1 = t1.encloses(i1[0]) ret2, i2 = intersect3d_ray_triangle(ray0, ray1, tri0, tri1, tri2) nose.tools.assert_equal(ret2.shape, (1, )) nose.tools.assert_equal(ret2[0] == 1, ret1) nose.tools.assert_equal(i2.shape, (1, 3)) if ret1: np.testing.assert_allclose(i2[0], map(float, [i1[0].x, i1[0].y, i1[0].z]))
def default_plane(pick: int) -> sy.Plane: """ """ x = sy.Point3D([30, 0, 0]) y = sy.Point3D([0, 30, 0]) z = sy.Point3D([0, 0, 30]) c = sy.Point3D([0, 0, 0]) if pick == 0: return sy.Plane(y, c, x) elif pick == 1: return sy.Plane(x, c, z) elif pick == 2: return sy.Plane(z, c, y) else: raise ValueError('Selection must be between 0 and 2')
def plane_1(a,b,c): ''' a,b,c : tuples with three element (x,y,z) ''' x, y , z = sp.symbols("x y z") plane_temp = sp.Plane(sp.Point3D(*a),sp.Point3D(*b),sp.Point3D(*c)) vn = plane_temp.normal_vector; return -(vn[0]*(x-a[0])+vn[1]*(y-a[1]))/vn[2] + a[2]
def make_angles_and_distances(pieces: Dict) -> pd.DataFrame: """Calculates the angles and distances from the vectors and planes. :param pieces: The SSE pieces to calculate the vectors from. """ data = { 'sse': [], 'layer': [], 'angles_layer': [], 'angles_floor': [], 'angles_side': [], 'points_layer': [], 'points_floor': [], 'points_side': [], 'tilted_layer': [], 'tilted_floor': [], 'tilted_side': [] } for layer in sorted(set([x[0] for x in pieces if len(x) == 1])): for sse in [x for x in pieces if len(x) == 3]: if abs(ascii_uppercase.find(layer) - ascii_uppercase.find(sse[0])) <= 1: data['sse'].append(sse) data['layer'].append(layer) for iplane, plane in enumerate(pieces[layer]): if TBcore.get_option('system', 'debug'): sys.stdout.write( 'PDB:{} geometry plane {} vs. sse {}\n'.format( plane, layer, sse)) syPlane = sy.Plane(sy.Point3D(pieces[layer][plane][0]), sy.Point3D(pieces[layer][plane][1]), sy.Point3D(pieces[layer][plane][2])) syLine = sy.Line(pieces[sse]['vector'][0], pieces[sse]['vector'][-1]) syPoint = sy.Point3D(*pieces[sse]['vector'][1]) data[f'angles_{plane}'].append( math.degrees(syPlane.angle_between(syLine))) data[f'points_{plane}'].append( float(syPlane.distance(syPoint))) data[f'tilted_{plane}'].append( float(syPlane.distance(default_plane(iplane)))) return pd.DataFrame(data)
def offset_face(self, fid): connected_edges = [ self.get_connected_edge(self.faces[fid][i], fid) for i in range(4) ] plane = self.face2plane(fid) origin = self.face_centre(fid) norm = sp.Point3D(plane.normal_vector) offset_vector = (sp.Point3D(self.center) - origin) offset_vector /= sp.Segment3D(sp.Point3D(0, 0, 0), offset_vector).length origin += offset_vector * random.uniform(-self.max_offset, self.max_offset) plane = sp.Plane(origin, normal_vector=norm) # find new points for face new_face_points = [] for ce in connected_edges: line = sp.Line3D(sp.Point3D(self.points[ce[0]]), sp.Point3D(self.points[ce[1]])) intersections = plane.intersection(line) if len(intersections) == 0: print("skip face offsetting - hex will not be valid") return new_point = intersections[0] new_point = [ new_point.x.evalf(), new_point.y.evalf(), new_point.z.evalf() ] new_face_points.append(new_point) if not self.is_b_not_far_than_a(self.points[ce[0]], self.points[ce[1]], new_point): print("skip face offsetting - hex will not be valid") return # replace old points with new for i in range(4): pid = self.faces[fid][i] self.points[pid] = new_face_points[i]
def rotate_face(self, fid): connected_edges = [ self.get_connected_edge(self.faces[fid][i], fid) for i in range(4) ] # rotate face plane around random axis with origin at face centre plane = self.face2plane(fid) origin = self.face_centre(fid) axis = plane.random_point() - plane.random_point() transform_matrix = Quaternion.from_axis_angle((axis[0], axis[1], axis[2]), random.uniform(-self.max_angle_offset, self.max_angle_offset) )\ .to_rotation_matrix((origin[0], origin[1], origin[2])) norm = sp.Point3D(plane.normal_vector) plane = sp.Plane(origin, normal_vector=norm.transform(transform_matrix)) # find new points for face new_face_points = [] for ce in connected_edges: line = sp.Line3D(sp.Point3D(self.points[ce[0]]), sp.Point3D(self.points[ce[1]])) new_point = plane.intersection(line)[0] new_point = [ new_point.x.evalf(), new_point.y.evalf(), new_point.z.evalf() ] new_face_points.append(new_point) if not self.is_b_not_far_than_a(self.points[ce[0]], self.points[ce[1]], new_point): print("skip face rotating - hex will not be valid") return # replace old points with new for i in range(4): pid = self.faces[fid][i] self.points[pid] = new_face_points[i]
# -*- coding: utf-8 -*- """ Main entry point for neurosegment """ import sympy as sp import matplotlib.pyplot as plt from preprocessing import read_nifti, skull_strip, sobelize, binary_by_percentile_threshold from preprocessing import calculate_projected_plane_coords, is_partnered, intersection_of_plane_with_slice from preprocessing import score_midsagittal px, py = (238, 242) arbitrary_plane = sp.Plane((0, 0, 10), (300, 300, 20), (300, 300, 10)) slice_num = 23 img_path = r'/Users/manusdonahue/Documents/Sky/Infarcts/Donahue_114402.XMLPARREC.dcm2niix/NIFTI/Donahue_114402.04.01.14-42-52.WIP_MJD_FLAIR_AX_3MM_SENSE.01.nii' img = read_nifti(img_path) stripped_img, mask = skull_strip(img) sobel_img = sobelize(stripped_img) edge_img, abs_thresh = binary_by_percentile_threshold(sobel_img, 3, invert=True) # note that when plotting with imshow, imaging conventions for coordinates are used # essentially x and y are swapped and the origin is at the upper left corner raw_data = img[:, :, slice_num] fig, ax = plt.subplots(2, 2)
def as_sympy_plane(self) -> S.Plane: return S.Plane(*self.sympy_vertices, normal_vector=self.normal)
def face2plane(self, fid): p1 = sp.Point3D(self.points[self.faces[fid][0]]) p2 = sp.Point3D(self.points[self.faces[fid][1]]) p3 = sp.Point3D(self.points[self.faces[fid][2]]) return sp.Plane(p1, p2, p3)
normvec[i] = edgevec[i] / edgelength wrappedmidpt = geometry.wrap_positions([mid], cell)[0] print("wrapped midpoint: ", wrappedmidpt) print("cut: ", cutrad, "midpoint: ", mid[0], mid[1], mid[2], "vec: ", edgevec[0], edgevec[1], edgevec[2], "normvec: ", normvec[0], normvec[1], normvec[2]) # declare sympy Point3D from UNWRAPPED midpoint # FIXME: not sure if this is the best thing to do though? should not matter if it is wrapped midpoint = sympy.Point3D(mid[0], mid[1], mid[2]) nodepoint1 = sympy.Point3D(node1[0], node1[1], node1[2]) nodepoint2 = sympy.Point3D(node2[0], node2[1], node2[2]) vecline = sympy.geometry.Line(nodepoint1, nodepoint2) # declare sympy Plane plane = sympy.Plane(sympy.Point3D(mid[0], mid[1], mid[2]), normal_vector=normvec) # declare radii dictionary radii = dict() # declare containers to store atoms within cutoff atomname = [] # atom names point3D = [] # atom centers projection3D = [] # projection of atom centers onto 3D plane projection2D = [] # parameterization of atom centers onto a 2D plane radius = [] # radius of atoms indices = [] allatomnames = [] allatompos = [] allatomnames_supercell = [] allatompos_supercell = []
import platform platform.platform() platform.python_version() import numpy as np import numpy.linalg as LA import math import sympy from sympy import var H = sympy.Point3D(-69.2, 89.23, 70.43) tockanax = -(-33.21 / 80.86) ravnina = sympy.Plane(sympy.Point3D(tockanax, 0, 0), (80.86, -66.12, -18.29)) presjeknaravnini = ravnina.projection(H) Hc = presjeknaravnini + H.direction_ratio(presjeknaravnini) E = sympy.Point3D(-32.6, 67.92, -51.91) print(round(Hc.distance(E), 5))
def reconstruct_room(candidate_virtual_sources, loudspeaker, dist_thresh, shoebox=True): """ This method uses the first-order virtual-sources to reconstruct the room: it processes the candidate virtual sources in the order of increasing distance from the loudspeaker to find the first-order virtual sources and add their planes to the list of half-spaces whose intersection determines the final room. :param candidate_virtual_sources: list of the coordinates of all the individuated virtual sources (it could contain even higher-order virtual sources) :param loudspeaker: x, y, z coordinates of the speaker location in the room :param dist_thresh: distance threshold (epsilon) :param shoebox: boolean to identify if the room is a shoebox :return: list of planes corresponding to the first-order virtual sources """ def combine(s1, s2): """ This method combines the virtual sources s1 and s2 to generate a higher-order virtual source; it is used as a criterion to discard higher-order virtual sources. :param s1: first virtual source coordinates :param s2: second virtual source coordinates :return: the coordinates of the higher order virtual source generated through the combination of s1 and s2 """ # p2 is a point on the hypothetical wall defined by s2, that is, a point on # the median plane between the loudspeaker and s2 p2 = (loudspeaker + s2) / 2 # n2 is the outward pointing unit normal n2 = (loudspeaker - s2) / np.linalg.norm(loudspeaker - s2) return s1 + 2 * np.dot((p2 - s1), n2) * n2 def perpendicular(a): """ This method computes the perpendicular to a given vector. :param a: the given vector :return: the perpendicular vector """ b = np.empty_like(a) b[0] = -a[1] b[1] = a[0] return b # Instantiating the array to contain the distance of each virtual source from the loudspeaker distances_from_speaker = [] # Computing the distances for source in candidate_virtual_sources: distances_from_speaker.append(np.linalg.norm(source - loudspeaker)) # Re-ordering the list of virtual sources according to their distance from the loudspeaker candidate_virtual_sources = np.array(candidate_virtual_sources) sorted_virtual_sources = candidate_virtual_sources[np.array( distances_from_speaker).argsort()][1:] # Initialize the list of planes that constitutes the room room = [] vertices = [] # Initialize the boolean mask to identify the first-order virtual sources deleted = np.array([False] * len(sorted_virtual_sources), dtype=bool) for i in range(len(sorted_virtual_sources)): for j in range(i): for k in range(i): # The following two conditions verify if the current virtual source is a combination of lower order # virtual sources: if so, it is deleted from the available candidates if j != k and k < i: if np.linalg.norm( combine(sorted_virtual_sources[j], sorted_virtual_sources[k]) - sorted_virtual_sources[i]) < dist_thresh: deleted[i] = True # If the room is a "Shoebox" it is possible to exploit geometric properties to filter out # "ghost" image sources from the first order reflections. if shoebox: # Array containing the direction of the axes passing through the source position directions = [] if len(loudspeaker) == 2: x = sp.Line(loudspeaker, loudspeaker + [0, 1]) y = sp.Line(loudspeaker, loudspeaker + [1, 0]) directions.append(x) directions.append(y) elif len(loudspeaker) == 3: planes = [] x = sp.Plane(loudspeaker, [1, 0, 0]) y = sp.Plane(loudspeaker, [0, 1, 0]) z = sp.Plane(loudspeaker, [0, 0, 1]) planes.append(x) planes.append(y) planes.append(z) for i in range(3): for j in range(i): directions.append(planes[i].intersection(planes[j])[0]) for i in range(len(sorted_virtual_sources)): if not deleted[i]: for index, direction in enumerate(directions): if direction.distance(sp.Point( sorted_virtual_sources[i])) < dist_thresh: break else: if index == len(directions) - 1: deleted[i] = True # If the virtual source is not a combination of lower order virtual sources, the corresponding plane # is built and it is added to the room's walls list for i in range(len(sorted_virtual_sources)): if not deleted[i]: # pi is a point on the hypothetical wall defined by si, that is, a point on # the median plane between the loudspeaker and si pi = (loudspeaker + sorted_virtual_sources[i]) / 2 # ni is the outward pointing unit normal ni = (loudspeaker - sorted_virtual_sources[i] ) / np.linalg.norm(loudspeaker - sorted_virtual_sources[i]) plane = {} if len(pi) == 2: ni_perp = perpendicular(ni) pi2 = pi + ni_perp plane = sp.Line(pi, pi2) elif len(pi) == 3: plane = sp.Plane(sp.Point3D(pi), normal_vector=ni) # If the room is empty, we add the first plane to the list of half-spaces whose intersection # determines the final room if len(room) == 0: room.append(plane) else: for wall in room: if len(plane.intersection(wall)) > 0: room.append(plane) break if plane not in room: deleted[i] = True if room[0].ambient_dimension == 2: for wall1 in range(len(room)): for wall2 in range(wall1): if wall1 != wall2: intersections = room[wall2].intersection(room[wall1]) if len(intersections) > 0: for intersection in intersections: if abs(float(intersection.x)) < 100 and abs( float(intersection.y)) < 100: vertices.append(intersection) if room[0].ambient_dimension == 3: planes_intersections = [] for wall1 in range(len(room)): for wall2 in range(wall1): if wall1 != wall2: planes_intersections.append(room[wall2].intersection( room[wall1])) for inter1 in range(len(planes_intersections)): for inter2 in range(inter1): if inter1 != inter2: intersections = planes_intersections[inter2][ 0].intersection(planes_intersections[inter1][0]) if len(intersections) > 0: for intersection in intersections: if abs(float(intersection.x)) < 100 and abs( float(intersection.y)) < 100 and abs( float(intersection.z) ) < 100 and intersection not in vertices: vertices.append(intersection) return room, vertices
import platform platform.platform() platform.python_version() import numpy as np import numpy.linalg as LA import math import sympy from sympy import var #Zadavanje ravnine pomoću tri nekolinearne točke T1 = sympy.Point3D(35, 33, -46) T2 = sympy.Point3D(-36, -40, -44) T3 = sympy.Point3D(0, -11, 48) rav = sympy.Plane(T1, T2, T3) print("Zadavanje ravnine pomoću tri nekolinearne točke: ", rav) #dvije ravnine pi1 = sympy.Plane(sympy.Point3D(0.92857, 0, 0), (-14, 7, -8)) print(pi1.equation()) pi2 = sympy.Plane(sympy.Point3D(0, 1.869565, 0), (21, -23, 32)) print(pi2.equation()) normala1 = pi1.intersection(pi2)[0] print(normala1.equation()) kut = rav.angle_between(normala1) print(kut) print(kut) kut2 = (round(kut, 10) * 180 / np.pi)
import sympy from sympy import var H = sympy.Point3D(18, -95, 56) pravac1 = sympy.Line3D(sympy.Point3D(10, -27, 24), sympy.Point3D(-17, -65, 63)) pravac2 = sympy.Line3D(sympy.Point3D(41, 54, 86), sympy.Point3D(43, 129, 32)) s1 = sympy.Matrix(pravac1.direction_ratio) s2 = sympy.Matrix(pravac2.direction_ratio) nor = s1.cross(s2) nor_pi1 = s1.cross(nor) pi1 = sympy.Plane(sympy.Point3D(10, -27, 24), nor_pi1) nor_pi2 = s2.cross(nor) pi2 = sympy.Plane(sympy.Point3D(41, 54, 86), nor_pi2) normala = pi1.intersection(pi2)[0] N1 = normala.intersection(pravac1)[0] N2 = normala.intersection(pravac2)[0] pravaca = sympy.Line3D(H, N1) pravacb = sympy.Line3D(H, N2) vektora = sympy.Matrix(pravaca.direction_ratio) vektorb = sympy.Matrix(pravacb.direction_ratio) cross = vektora.cross(vektorb).norm()
print("tocke A, B i D nisu kolinearne: ", sympy.Point3D.are_collinear(A, B, D), "\n") #kosinus smjera radij vektora A = sympy.Point3D(1, -2, 3) O = sympy.Point3D(0, 0, 0) print("kosinus smjera radij vektora: ", O.direction_cosine(A), "\n") #kosinus smjera vektora odredjenog s dvije tocke A = sympy.Point3D(1, 4, -2) B = sympy.Point3D(0, -2, 1) print("kosinus smjera vektora odredjenog s dvije tocke: ", A.direction_cosine(B), "\n") #zadavanje ravnine pomocu tocke i vektora normale rav = sympy.Plane(sympy.Point3D(1, 2, 1), (-2, 3, -1)) print("Ravnina uz pomoc tocke i vektora normale: ", rav) #opci oblik jednadzbe ravnine print("opci oblik jednadzbe ravnine: ", rav.equation()) #slucajana tocka u ravnini ranT = rav.random_point() print("Slucajna tocak u ravnini: ", ranT) from sympy import var #parametarska jednadzba ravnine u, v = var('u v') par = rav.arbitrary_point(u, v) print("parametarska jednadzba ravnine: ", par)