Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated the algo for SP3D2 #12

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion molecule-visulaiser/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ const MoleculeVisualizer = () => {
H: 0,
O: 0,
N: 0,
S: 0,
F: 0,
});

const [compoundFormula, setCompoundFormula] = useState("");
Expand Down Expand Up @@ -297,6 +299,8 @@ const MoleculeVisualizer = () => {
{ value: "H", label: "H" },
{ value: "O", label: "O" },
{ value: "N", label: "N" },
{ value: "S", label: "S" },
{ value: "F", label: "F" },
];

const getBondMenuItems = () => {
Expand All @@ -315,7 +319,7 @@ const MoleculeVisualizer = () => {
return bondMenuItems;
};

const sampleMolecules = ["CH4", "C2H6", "C6H6", "H2O"];
const sampleMolecules = ["CH4", "C2H6", "C6H6", "H2O", "SF6"];

return (
<div className="flex flex-col h-screen bg-[#141414] font-inter">
Expand Down
24 changes: 24 additions & 0 deletions molecule-visulaiser/src/components/EditMolecule.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,29 @@ export default function EditMolecule({
getCoordinates(water);
setMolecule(water);
break;
case "SF6":
const sulphurHexaFluoride = new Molecule();

addAtoms(sulphurHexaFluoride, createAtomNode("S0", "sp3d2", "S"));
addAtoms(sulphurHexaFluoride, createAtomNode("F0", "sp", "F"));
addAtoms(sulphurHexaFluoride, createAtomNode("F1", "sp", "F"));
addAtoms(sulphurHexaFluoride, createAtomNode("F2", "sp", "F"));
addAtoms(sulphurHexaFluoride, createAtomNode("F3", "sp", "F"));
addAtoms(sulphurHexaFluoride, createAtomNode("F4", "sp", "F"));
addAtoms(sulphurHexaFluoride, createAtomNode("F5", "sp", "F"));

addBonds(sulphurHexaFluoride, "S0", "F0", true, false, false); //consider only the sngle bond
addBonds(sulphurHexaFluoride, "S0", "F1", true, false, false);
addBonds(sulphurHexaFluoride, "S0", "F2", true, false, false);
addBonds(sulphurHexaFluoride, "S0", "F3", true, false, false);
addBonds(sulphurHexaFluoride, "S0", "F4", true, false, false);
addBonds(sulphurHexaFluoride, "S0", "F5", true, false, false);

setAtomCounters({ C: 0, H: 0, O: 0, N: 0, S: 1, F: 6 });
getCoordinates(sulphurHexaFluoride);
setMolecule(sulphurHexaFluoride);
break;

default:
break;
}
Expand Down Expand Up @@ -237,6 +260,7 @@ export default function EditMolecule({
<FormControlLabel value="sp" control={<Radio />} label="sp" />
<FormControlLabel value="sp2" control={<Radio />} label="sp2" />
<FormControlLabel value="sp3" control={<Radio />} label="sp3" />
<FormControlLabel value="sp3d2" control={<Radio />} label="sp3d2" />
</RadioGroup>
<Button
type="submit"
Expand Down
132 changes: 111 additions & 21 deletions molecule-visulaiser/src/components/GraphADT.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,38 +5,111 @@ export class atomNode {
this.atomSymbol = atomSymbol;
this.coordinates = [0, 0, 0];
this.connections = [];
this.bondAngles = new Map(); // Store bond angles for each connected atom
}
}

export class Molecule {
constructor() {
this.adjacencyList = {};
this.atomList = [];
this.bondAngles = new Map(); // Store all bond angles in the molecule
}

getNeighbours(atom) {
if (atom && this.adjacencyList[atom.atomName]) {
return this.adjacencyList[atom.atomName].map(({ atomName }) =>
this.atomList.find((a) => a.atomName === atomName)
);
calculateBondAngle(atom1, atom2, atom3) {
if (!atom1.coordinates || !atom2.coordinates || !atom3.coordinates) {
return null;
}

// Calculate vectors
const vector1 = [
atom1.coordinates[0] - atom2.coordinates[0],
atom1.coordinates[1] - atom2.coordinates[1],
atom1.coordinates[2] - atom2.coordinates[2]
];

const vector2 = [
atom3.coordinates[0] - atom2.coordinates[0],
atom3.coordinates[1] - atom2.coordinates[1],
atom3.coordinates[2] - atom2.coordinates[2]
];

const mag1 = Math.sqrt(vector1.reduce((sum, val) => sum + val * val, 0));
const mag2 = Math.sqrt(vector2.reduce((sum, val) => sum + val * val, 0));

// dot product
const dotProduct = vector1.reduce((sum, val, i) => sum + val * vector2[i], 0);

// Calculate angle in radians and convert
const angle = Math.acos(dotProduct / (mag1 * mag2)) * (180 / Math.PI);

return angle;
}

//Store bond angle
storeBondAngle(centralAtom, atom1, atom2) {
const angle = this.calculateBondAngle(atom1, centralAtom, atom2);
if (angle !== null) {
//created keys
const angleKey = `${atom1.atomName}-${centralAtom.atomName}-${atom2.atomName}`;
this.bondAngles.set(angleKey, angle);

// Store in the central atom's
centralAtom.bondAngles.set(angleKey, angle);
}
}

// Get bond angle between specific atoms
getBondAngle(centralAtom, atom1, atom2) {
const angleKey = `${atom1.atomName}-${centralAtom.atomName}-${atom2.atomName}`;
return this.bondAngles.get(angleKey);
}

// Get all bond angles for a specific atom
getAtomBondAngles(centralAtom) {
const angles = {};
if (!centralAtom.bondAngles) return angles;

for (const [key, angle] of centralAtom.bondAngles) {
angles[key] = angle;
}
return angles;
}
return [];
}

//stroitng
storeExpectedAngles(atom) {
const hybridAngles = {
'sp': 180,
'sp2': 120,
'sp3': 109.5,
'sp3d2': 90 // Octahedral geometry
};

if (hybridAngles[atom.hybridisation]) {
atom.expectedAngle = hybridAngles[atom.hybridisation];
}
}

// Existing methods...
getNeighbours(atom) {
if (atom && this.adjacencyList[atom.atomName]) {
return this.adjacencyList[atom.atomName].map(({ atomName }) =>
this.atomList.find((a) => a.atomName === atomName)
);
}
return [];
}

addAtoms(atom) {
if (!this.adjacencyList[atom.atomName]) {
this.adjacencyList[atom.atomName] = [];
this.atomList.push(atom);
} else {
this.storeExpectedAngles(atom); // Store expected angles when adding atom
}
}

addBond(atom1, atom2, isSingleBond = false, isDoubleBond = false, isTripleBond = false) {
if (
this.adjacencyList[atom1.atomName] &&
this.adjacencyList[atom2.atomName]
) {
if (this.adjacencyList[atom1.atomName] && this.adjacencyList[atom2.atomName]) {
let flag1 = 0;
for (let i = 0; i < this.adjacencyList[atom1.atomName].length; i++) {
if (this.adjacencyList[atom1.atomName][i].atomName === atom2.atomName) {
Expand All @@ -47,12 +120,12 @@ export class Molecule {
if (!flag1) {
this.adjacencyList[atom1.atomName].push({
atomName: atom2.atomName,
isSingleBond: isSingleBond && !isDoubleBond && !isTripleBond,
isDoubleBond: !isSingleBond && isDoubleBond && !isTripleBond,
isTripleBond: !isSingleBond && !isDoubleBond && isTripleBond
isSingleBond,
isDoubleBond,
isTripleBond
});
}

let flag2 = 0;
for (let i = 0; i < this.adjacencyList[atom2.atomName].length; i++) {
if (this.adjacencyList[atom2.atomName][i].atomName === atom1.atomName) {
Expand All @@ -63,12 +136,29 @@ export class Molecule {
if (!flag2) {
this.adjacencyList[atom2.atomName].push({
atomName: atom1.atomName,
isSingleBond: isSingleBond && !isDoubleBond && !isTripleBond,
isDoubleBond: !isSingleBond && isDoubleBond && !isTripleBond,
isTripleBond: !isSingleBond && !isDoubleBond && isTripleBond
isSingleBond,
isDoubleBond,
isTripleBond
});
}

// Calculate and store bond angles after adding new bond
const neighbours1 = this.getNeighbours(atom1);
const neighbours2 = this.getNeighbours(atom2);

// Store angles for atom1's bonds
for (let i = 0; i < neighbours1.length - 1; i++) {
for (let j = i + 1; j < neighbours1.length; j++) {
this.storeBondAngle(atom1, neighbours1[i], neighbours1[j]);
}
}

// Store angles for atom2's bonds
for (let i = 0; i < neighbours2.length - 1; i++) {
for (let j = i + 1; j < neighbours2.length; j++) {
this.storeBondAngle(atom2, neighbours2[i], neighbours2[j]);
}
}
}
}

}
}
106 changes: 103 additions & 3 deletions molecule-visulaiser/src/components/Molecule.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ export function addAtoms(molecule, atom) {
molecule.addAtoms(atom);
}

export function addBonds(molecule, atom1Name, atom2Name, isSingleBond, isDoubleBond, isTripleBond) {
export function addBonds(
molecule,
atom1Name,
atom2Name,
isSingleBond,
isDoubleBond,
isTripleBond
) {
const atom1 = molecule.atomList.find((atom) => atom.atomName === atom1Name);
const atom2 = molecule.atomList.find((atom) => atom.atomName === atom2Name);

Expand Down Expand Up @@ -39,9 +46,83 @@ export function findCentralAtoms(molecule) {
return centralAtoms;
}

// Calculate Coordiantes of the atoms in 3D Plane.
export function getCoordinates(molecule) {


function calcSp3d2bondDirection(parentAtom, currentAtom) {
if (!parentAtom || !parentAtom.coordinates) {
console.error("Invalid parent atom");
return [1, 0, 0];
}

const existingBonds = (parentAtom.bonds || [])
.filter(bond => bond.atomEnd && bond.atomEnd !== currentAtom)
.map(bond => {
if (!bond.atomEnd.coordinates) return null;
// Calculate direction using existing coordinates
return normalizeVector([
bond.atomEnd.coordinates[0] - parentAtom.coordinates[0],
bond.atomEnd.coordinates[1] - parentAtom.coordinates[1],
bond.atomEnd.coordinates[2] - parentAtom.coordinates[2]
]);
})
.filter(dir => dir !== null);

if (existingBonds.length === 0) {
return [1, 0, 0];
}

if (existingBonds.length === 1) {
return [-1, 0, 0];
}

if (existingBonds.length === 2) {
return [0, 1, 0];
}
if (existingBonds.length === 3) {
return [0, -1, 0];
}

if (existingBonds.length === 4) {
return [0, 0, 1];
}
if (existingBonds.length === 5) {
return [0, 0, -1];
}

return [1, 0, 0];
}

// Helper function for vector normalization
function normalizeVector(vector) {
const magnitude = Math.sqrt(vector[0] * vector[0] + vector[1] * vector[1] + vector[2] * vector[2]);
return magnitude === 0 ? vector : vector.map(component => component / magnitude);
}

function validatePlanarArrangement(bonds) {
if (bonds.length < 4) return false;

const planarBonds = bonds.slice(0, 4);
return planarBonds.every(bond => Math.abs(bond[2]) < 0.1);
}

function getPlaneNormal(bonds) {
if (bonds.length < 2) return [0, 0, 1];

const v1 = bonds[0];
const v2 = bonds[1];

return normalizeVector([
v1[1] * v2[2] - v1[2] * v2[1],
v1[2] * v2[0] - v1[0] * v2[2],
v1[0] * v2[1] - v1[1] * v2[0]
]);
}

export function getCoordinates(molecule) {
if (!molecule || !molecule.coordinates || molecule.coordinates.length < 3) {
console.error("Invalid molecule or coordinates:", molecule);
return null; // or a default value, e.g., [0, 0, 0]
}
// Constant Angles defined for respective hybridisations.
const angles = {
sp: { angleX: Math.PI, angleY: 0, angleZ: 0 },
Expand All @@ -51,6 +132,12 @@ export function getCoordinates(molecule) {
angleY: 0.955 * Math.PI,
angleZ: 0.615 * Math.PI,
},
//octahedral geometry.
sp3d2: {
angleX: Math.PI / 2,
angleY: Math.PI / 2,
angleZ: Math.PI / 2,
},
};

// Get Central Atoms of the Molecule.
Expand Down Expand Up @@ -176,6 +263,19 @@ export function getCoordinates(molecule) {
firstCoordinate,
secondCoordinate
);
if (parentAtom.hybridisation === "sp3d2") {
newDirection = calcSp3d2bondDirection(parentAtom, currentAtom);
directionVectorStack.push(newDirection);

// i implemented the new coordinatess inside the sp3d2 section
const newCoordinates = [
parentCoordinates[0] + bondlength * newDirection[0],
parentCoordinates[1] + bondlength * newDirection[1],
parentCoordinates[2] + bondlength * newDirection[2],
];
currentAtom.coordinates = newCoordinates;
continue;
}
directionVectorStack.push(newDirection);

console.log("New Direction:", newDirection);
Expand Down