Is it possible to determine if a line segment is present between two points on a 3d graphic object?
Hello everyone. I'm working on a program which plots 3D molecular structures and associated point group symmetries. I've had some issues figuring out how to fill in the remaining single bonds of a six member ring (aromatic class) after the user dictates where double bonds should be placed. These aromatics are basically 6 member cycle graphs for the purposes of my problem. Is there any way to evaluate two coordinates (atoms) on a 3d graphic object (molecule) and check if a line segment (bond) has already been added between them? By necessity any pi (double) bond should only be connected to the adjacent, (non pi-bonded) atom. So for example if there was a pi bond present between Atoms 1 and 2 of a ring then we should have single bonds between A6-A1 and A2-A3. The code below is how I am currently approaching that problem.
A1,A2,A3,A4,A6 are fixed, three dimensional coordinates associated with each position on the ring.
Bonds = str(input('Enter pi bond atomic pair in format "A1-A2" or type PLOT: '))
while (Bonds != 'PLOT'):
Bonds2 = Bonds.split('-')
for bond in Bonds2:
if bond == 'A1':
pi_list.append(A1)
elif bond == 'A2':
pi_list.append(A2)
elif bond == 'A3':
pi_list.append(A3)
elif bond == 'A4':
pi_list.append(A4)
elif bond == 'A5':
pi_list.append(A5)
elif bond == 'A6':
pi_list.append(A6)
if pi_list != []:
x += pi_bond(x,pi_list[0], pi_list[1])
for atom in Coords:
for pi_atom in pi_list:
if (atom != pi_list[0]) and (atom != pi_list[1]) and (float(distance(pi_atom,atom))==float(distance(A1,A2))):
x += single_bond(pi_atom, atom)
pi_list.clear()
if (Bonds == 'PLOT'):
break
Bonds = str(input('Enter additional pi bonds or type PLOT: '))
Can anyone think of a more elegant way to approach this?
Here is the function I am currently using to add a double bond between two points:
def pi_bond(x,Cx,Cy):
X = 0.05
if Cx[1] == Cy[1]:
Ca = Cx[1]-X
Cb = Cx[1]+X
Cc = Cy[1]-X
Cd = Cy[1]+X
Cx1 = (Cx[0], Ca, Cx[2])
Cx2 = (Cx[0], Cb, Cx[2])
Cy1 = (Cy[0], Cc, Cy[2])
Cy2 = (Cy[0], Cd, Cy[2])
x += LineSegment(Cx1, Cy1, 1, color='white', axes=False, frame=False)
x += LineSegment(Cx2, Cy2, 1, color='white', axes=False, frame=False)
return x
else:
Ca = Cx[2]-X
Cb = Cx[2]+X
Cc = Cy[2]-X
Cd = Cy[2]+X
Cx1 = (Cx[0], Cx[1], Ca)
Cx2 = (Cx[0], Cx[1], Cb)
Cy1 = (Cy[0], Cy[1], Cc)
Cy2 = (Cy[0], Cy[1], Cd)
x += LineSegment(Cx1, Cy1, 1, color='white', axes=False, frame=False)
x += LineSegment(Cx2, Cy2, 1, color='white', axes=False, frame=False)
return x
I would maintain all of the data for the molecule without doing any plotting, for example as a dictionary. Then it's easy to add and delete entries. When you're ready to plot, create the plot.
Am I understanding correctly that you're suggesting I create a default position dictionary that would like something like:
This way when a user adds a pi bond pair ie A1-A2 I can delete the pairing from the default dictionary and add them to a second dictionary for double bonds or something to that effect. Much more elegant. Thank you for the suggestion.
Oh, and to try to answer your original question: I don't know of any way to determine whether a line segment is present in a graphics object. I am not an expert in the graphics part of Sage, though.
I think this will be a much better approach and I imagine any answer to that question would have taken me down a much more complicated rabbit hole.
I have fixed the issue and updated the code. Thank you again.