AI_ChemTutor / Pages /Items /Molecular_View.txt
Abbasaabdul's picture
Upload 7 files
b3a7bda verified
import React, { useState, useEffect, useRef } from "react";
import * as THREE from "three";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Input } from "@/components/ui/input";
import { Badge } from "@/components/ui/badge";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import {
Atom,
RotateCcw,
Search,
Play,
Pause,
Info,
Filter
} from "lucide-react";
// Comprehensive molecules database organized by category
const MOLECULES = [
// Simple Molecules
{
name: "Hydrogen Gas (H₂)",
formula: "H2",
category: "simple",
atoms: [
{ element: "H", position: [-0.37, 0, 0], color: "#ffffff" },
{ element: "H", position: [0.37, 0, 0], color: "#ffffff" }
],
bonds: [{ from: 0, to: 1 }],
description: "The simplest and most abundant element in the universe, existing as diatomic molecules under normal conditions."
},
{
name: "Oxygen Gas (O₂)",
formula: "O2",
category: "simple",
atoms: [
{ element: "O", position: [-0.60, 0, 0], color: "#ff0000" },
{ element: "O", position: [0.60, 0, 0], color: "#ff0000" }
],
bonds: [{ from: 0, to: 1 }],
description: "Essential for respiration and combustion, making up about 21% of Earth's atmosphere."
},
{
name: "Nitrogen Gas (N₂)",
formula: "N2",
category: "simple",
atoms: [
{ element: "N", position: [-0.55, 0, 0], color: "#0000ff" },
{ element: "N", position: [0.55, 0, 0], color: "#0000ff" }
],
bonds: [{ from: 0, to: 1 }],
description: "Makes up about 78% of Earth's atmosphere. The triple bond makes it very stable."
},
{
name: "Carbon Dioxide (CO₂)",
formula: "CO2",
category: "simple",
atoms: [
{ element: "C", position: [0, 0, 0], color: "#404040" },
{ element: "O", position: [-1.16, 0, 0], color: "#ff0000" },
{ element: "O", position: [1.16, 0, 0], color: "#ff0000" }
],
bonds: [{ from: 0, to: 1 }, { from: 0, to: 2 }],
description: "A greenhouse gas produced by combustion and respiration, absorbed by plants during photosynthesis."
},
{
name: "Water (H₂O)",
formula: "H2O",
category: "simple",
atoms: [
{ element: "O", position: [0, 0, 0], color: "#ff0000" },
{ element: "H", position: [0.96, 0, 0], color: "#ffffff" },
{ element: "H", position: [-0.24, 0.93, 0], color: "#ffffff" }
],
bonds: [{ from: 0, to: 1 }, { from: 0, to: 2 }],
description: "The most essential compound for life, consisting of two hydrogen atoms bonded to one oxygen atom."
},
{
name: "Ammonia (NH₃)",
formula: "NH3",
category: "simple",
atoms: [
{ element: "N", position: [0, 0, 0], color: "#0000ff" },
{ element: "H", position: [0.94, 0, 0.33], color: "#ffffff" },
{ element: "H", position: [-0.47, 0.82, 0.33], color: "#ffffff" },
{ element: "H", position: [-0.47, -0.82, 0.33], color: "#ffffff" }
],
bonds: [{ from: 0, to: 1 }, { from: 0, to: 2 }, { from: 0, to: 3 }],
description: "A basic compound used in fertilizers and cleaning products, with a trigonal pyramidal shape."
},
// Hydrocarbons - Alkanes
{
name: "Methane (CH₄)",
formula: "CH4",
category: "hydrocarbons",
atoms: [
{ element: "C", position: [0, 0, 0], color: "#404040" },
{ element: "H", position: [0.63, 0.63, 0.63], color: "#ffffff" },
{ element: "H", position: [-0.63, -0.63, 0.63], color: "#ffffff" },
{ element: "H", position: [-0.63, 0.63, -0.63], color: "#ffffff" },
{ element: "H", position: [0.63, -0.63, -0.63], color: "#ffffff" }
],
bonds: [{ from: 0, to: 1 }, { from: 0, to: 2 }, { from: 0, to: 3 }, { from: 0, to: 4 }],
description: "The simplest hydrocarbon and main component of natural gas, featuring a tetrahedral geometry."
},
{
name: "Ethane (C₂H₆)",
formula: "C2H6",
category: "hydrocarbons",
atoms: [
{ element: "C", position: [-0.77, 0, 0], color: "#404040" },
{ element: "C", position: [0.77, 0, 0], color: "#404040" },
{ element: "H", position: [-1.17, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-1.17, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-1.17, 0, -1.03], color: "#ffffff" },
{ element: "H", position: [1.17, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [1.17, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [1.17, 0, -1.03], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 0, to: 2 }, { from: 0, to: 3 }, { from: 0, to: 4 },
{ from: 1, to: 5 }, { from: 1, to: 6 }, { from: 1, to: 7 }
],
description: "A simple alkane used as fuel, with free rotation around the C-C single bond."
},
{
name: "Propane (C₃H₈)",
formula: "C3H8",
category: "hydrocarbons",
atoms: [
{ element: "C", position: [-1.27, 0, 0], color: "#404040" },
{ element: "C", position: [0, 0, 0], color: "#404040" },
{ element: "C", position: [1.27, 0, 0], color: "#404040" },
{ element: "H", position: [-1.67, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-1.67, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-1.67, 0, -1.03], color: "#ffffff" },
{ element: "H", position: [0, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [0, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [1.67, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [1.67, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [1.67, 0, -1.03], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 1, to: 2 },
{ from: 0, to: 3 }, { from: 0, to: 4 }, { from: 0, to: 5 },
{ from: 1, to: 6 }, { from: 1, to: 7 },
{ from: 2, to: 8 }, { from: 2, to: 9 }, { from: 2, to: 10 }
],
description: "A common fuel gas used for heating, grilling, and as vehicle fuel (LPG)."
},
// Alkenes
{
name: "Ethene (C₂H₄)",
formula: "C2H4",
category: "hydrocarbons",
atoms: [
{ element: "C", position: [-0.67, 0, 0], color: "#404040" },
{ element: "C", position: [0.67, 0, 0], color: "#404040" },
{ element: "H", position: [-1.23, 0.93, 0], color: "#ffffff" },
{ element: "H", position: [-1.23, -0.93, 0], color: "#ffffff" },
{ element: "H", position: [1.23, 0.93, 0], color: "#ffffff" },
{ element: "H", position: [1.23, -0.93, 0], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 0, to: 2 }, { from: 0, to: 3 },
{ from: 1, to: 4 }, { from: 1, to: 5 }
],
description: "The simplest alkene with a C=C double bond, used to make polyethylene plastic."
},
// Aromatic Compounds
{
name: "Benzene (C₆H₆)",
formula: "C6H6",
category: "aromatics",
atoms: [
{ element: "C", position: [1.40, 0, 0], color: "#404040" },
{ element: "C", position: [0.70, 1.21, 0], color: "#404040" },
{ element: "C", position: [-0.70, 1.21, 0], color: "#404040" },
{ element: "C", position: [-1.40, 0, 0], color: "#404040" },
{ element: "C", position: [-0.70, -1.21, 0], color: "#404040" },
{ element: "C", position: [0.70, -1.21, 0], color: "#404040" },
{ element: "H", position: [2.48, 0, 0], color: "#ffffff" },
{ element: "H", position: [1.24, 2.15, 0], color: "#ffffff" },
{ element: "H", position: [-1.24, 2.15, 0], color: "#ffffff" },
{ element: "H", position: [-2.48, 0, 0], color: "#ffffff" },
{ element: "H", position: [-1.24, -2.15, 0], color: "#ffffff" },
{ element: "H", position: [1.24, -2.15, 0], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 1, to: 2 }, { from: 2, to: 3 },
{ from: 3, to: 4 }, { from: 4, to: 5 }, { from: 5, to: 0 },
{ from: 0, to: 6 }, { from: 1, to: 7 }, { from: 2, to: 8 },
{ from: 3, to: 9 }, { from: 4, to: 10 }, { from: 5, to: 11 }
],
description: "An aromatic hydrocarbon with a ring of six carbon atoms, fundamental in organic chemistry."
},
{
name: "Toluene (C₇H₈)",
formula: "C7H8",
category: "aromatics",
atoms: [
{ element: "C", position: [1.40, 0, 0], color: "#404040" },
{ element: "C", position: [0.70, 1.21, 0], color: "#404040" },
{ element: "C", position: [-0.70, 1.21, 0], color: "#404040" },
{ element: "C", position: [-1.40, 0, 0], color: "#404040" },
{ element: "C", position: [-0.70, -1.21, 0], color: "#404040" },
{ element: "C", position: [0.70, -1.21, 0], color: "#404040" },
{ element: "C", position: [-2.87, 0, 0], color: "#404040" }, // methyl group
{ element: "H", position: [2.48, 0, 0], color: "#ffffff" },
{ element: "H", position: [1.24, 2.15, 0], color: "#ffffff" },
{ element: "H", position: [-1.24, 2.15, 0], color: "#ffffff" },
{ element: "H", position: [-1.24, -2.15, 0], color: "#ffffff" },
{ element: "H", position: [1.24, -2.15, 0], color: "#ffffff" },
{ element: "H", position: [-3.27, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-3.27, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-3.27, 0, -1.03], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 1, to: 2 }, { from: 2, to: 3 },
{ from: 3, to: 4 }, { from: 4, to: 5 }, { from: 5, to: 0 },
{ from: 3, to: 6 }, { from: 0, to: 7 }, { from: 1, to: 8 },
{ from: 2, to: 9 }, { from: 4, to: 10 }, { from: 5, to: 11 },
{ from: 6, to: 12 }, { from: 6, to: 13 }, { from: 6, to: 14 }
],
description: "Methylbenzene, used as a solvent and in the production of other chemicals."
},
// Alcohols
{
name: "Methanol (CH₄O)",
formula: "CH4O",
category: "alcohols",
atoms: [
{ element: "C", position: [0, 0, 0], color: "#404040" },
{ element: "O", position: [1.43, 0, 0], color: "#ff0000" },
{ element: "H", position: [-0.51, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-0.51, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-0.51, 0, -1.03], color: "#ffffff" },
{ element: "H", position: [1.83, 0, 0.96], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 0, to: 2 }, { from: 0, to: 3 },
{ from: 0, to: 4 }, { from: 1, to: 5 }
],
description: "The simplest alcohol, used as fuel additive and solvent. Highly toxic to humans."
},
{
name: "Ethanol (C₂H₆O)",
formula: "C2H6O",
category: "alcohols",
atoms: [
{ element: "C", position: [-0.77, 0.36, 0], color: "#404040" },
{ element: "C", position: [0.77, 0.36, 0], color: "#404040" },
{ element: "O", position: [1.2, -0.8, 0], color: "#ff0000" },
{ element: "H", position: [-1.1, 0.7, 1], color: "#ffffff" },
{ element: "H", position: [-1.1, 0.7, -1], color: "#ffffff" },
{ element: "H", position: [-1.2, -0.6, 0], color: "#ffffff" },
{ element: "H", position: [1.1, 1.3, 0], color: "#ffffff" },
{ element: "H", position: [1.1, -0.2, 1], color: "#ffffff" },
{ element: "H", position: [2.1, -0.6, 0], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 1, to: 2 },
{ from: 0, to: 3 }, { from: 0, to: 4 }, { from: 0, to: 5 },
{ from: 1, to: 6 }, { from: 1, to: 7 },
{ from: 2, to: 8 }
],
description: "The alcohol found in beverages, also used as fuel and solvent."
},
// Acids
{
name: "Formic Acid (HCOOH)",
formula: "HCOOH",
category: "acids",
atoms: [
{ element: "C", position: [0, 0, 0], color: "#404040" },
{ element: "O", position: [1.23, -0.67, 0], color: "#ff0000" },
{ element: "O", position: [0.31, 1.34, 0], color: "#ff0000" },
{ element: "H", position: [-1.08, 0.11, 0], color: "#ffffff" },
{ element: "H", position: [1.19, 1.14, 0], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 0, to: 2 }, { from: 0, to: 3 }, { from: 2, to: 4 }
],
description: "The simplest carboxylic acid, found in ant stings and used as a preservative."
},
{
name: "Acetic Acid (CH₃COOH)",
formula: "CH3COOH",
category: "acids",
atoms: [
{ element: "C", position: [-1.27, 0, 0], color: "#404040" },
{ element: "C", position: [0, 0, 0], color: "#404040" },
{ element: "O", position: [1.23, -0.67, 0], color: "#ff0000" },
{ element: "O", position: [0.31, 1.34, 0], color: "#ff0000" },
{ element: "H", position: [-1.67, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-1.67, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-1.67, 0, -1.03], color: "#ffffff" },
{ element: "H", position: [1.19, 1.14, 0], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 1, to: 2 }, { from: 1, to: 3 },
{ from: 0, to: 4 }, { from: 0, to: 5 }, { from: 0, to: 6 }, { from: 3, to: 7 }
],
description: "Found in vinegar, used as food preservative and in chemical synthesis."
},
// Biomolecules - Amino Acids
{
name: "Glycine (NH₂CH₂COOH)",
formula: "C2H5NO2",
category: "biomolecules",
atoms: [
{ element: "N", position: [-2.14, 0, 0], color: "#0000ff" },
{ element: "C", position: [-0.67, 0, 0], color: "#404040" },
{ element: "C", position: [0.67, 0, 0], color: "#404040" },
{ element: "O", position: [1.23, -1.15, 0], color: "#ff0000" },
{ element: "O", position: [1.23, 1.15, 0], color: "#ff0000" },
{ element: "H", position: [-2.54, 0.81, 0.41], color: "#ffffff" },
{ element: "H", position: [-2.54, -0.81, 0.41], color: "#ffffff" },
{ element: "H", position: [-0.67, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-0.67, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [2.17, 1.08, 0], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 1, to: 2 }, { from: 2, to: 3 }, { from: 2, to: 4 },
{ from: 0, to: 5 }, { from: 0, to: 6 }, { from: 1, to: 7 }, { from: 1, to: 8 }, { from: 4, to: 9 }
],
description: "The simplest amino acid, essential for protein synthesis and neurotransmitter function."
},
// Sugars
{
name: "Glucose (C₆H₁₂O₆)",
formula: "C6H12O6",
category: "biomolecules",
atoms: [
{ element: "C", position: [0, 0, 0], color: "#404040" },
{ element: "C", position: [1.25, 0.72, 0], color: "#404040" },
{ element: "C", position: [1.25, 2.17, 0], color: "#404040" },
{ element: "C", position: [0, 2.89, 0], color: "#404040" },
{ element: "C", position: [-1.25, 2.17, 0], color: "#404040" },
{ element: "O", position: [-1.25, 0.72, 0], color: "#ff0000" },
{ element: "O", position: [2.5, 0, 0], color: "#ff0000" },
{ element: "O", position: [2.5, 2.89, 0], color: "#ff0000" },
{ element: "O", position: [0, 4.34, 0], color: "#ff0000" },
{ element: "O", position: [-2.5, 2.89, 0], color: "#ff0000" },
{ element: "C", position: [-2.5, 4.34, 0], color: "#404040" },
{ element: "O", position: [-3.75, 5.06, 0], color: "#ff0000" }
],
bonds: [
{ from: 0, to: 1 }, { from: 1, to: 2 }, { from: 2, to: 3 }, { from: 3, to: 4 },
{ from: 4, to: 5 }, { from: 5, to: 0 }, { from: 1, to: 6 }, { from: 2, to: 7 },
{ from: 3, to: 8 }, { from: 4, to: 9 }, { from: 9, to: 10 }, { from: 10, to: 11 }
],
description: "The primary source of energy for cells, essential for metabolism in all living organisms."
},
// Inorganic Compounds
{
name: "Hydrogen Chloride (HCl)",
formula: "HCl",
category: "inorganic",
atoms: [
{ element: "H", position: [-0.63, 0, 0], color: "#ffffff" },
{ element: "Cl", position: [0.63, 0, 0], color: "#00ff00" }
],
bonds: [{ from: 0, to: 1 }],
description: "A strong acid when dissolved in water (hydrochloric acid), found in stomach acid."
},
{
name: "Sodium Chloride (NaCl)",
formula: "NaCl",
category: "inorganic",
atoms: [
{ element: "Na", position: [-1.4, 0, 0], color: "#ab5cf2" },
{ element: "Cl", position: [1.4, 0, 0], color: "#00ff00" }
],
bonds: [{ from: 0, to: 1 }],
description: "Common table salt, essential for life and widely used in food preservation."
},
{
name: "Sulfuric Acid (H₂SO₄)",
formula: "H2SO4",
category: "inorganic",
atoms: [
{ element: "S", position: [0, 0, 0], color: "#ffff00" },
{ element: "O", position: [0, 1.5, 0], color: "#ff0000" },
{ element: "O", position: [1.3, -0.75, 0], color: "#ff0000" },
{ element: "O", position: [-1.3, -0.75, 0], color: "#ff0000" },
{ element: "O", position: [0, 0, 1.5], color: "#ff0000" },
{ element: "H", position: [0, 2.4, 0], color: "#ffffff" },
{ element: "H", position: [0, 0, 2.4], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 0, to: 2 }, { from: 0, to: 3 }, { from: 0, to: 4 },
{ from: 1, to: 5 }, { from: 4, to: 6 }
],
description: "One of the most important industrial chemicals, used in batteries and chemical synthesis."
},
// Pharmaceuticals
{
name: "Aspirin (C₉H₈O₄)",
formula: "C9H8O4",
category: "pharmaceuticals",
atoms: [
{ element: "C", position: [0, 0, 0], color: "#404040" },
{ element: "C", position: [1.4, 0, 0.8], color: "#404040" },
{ element: "C", position: [1.4, 0, 2.2], color: "#404040" },
{ element: "C", position: [0, 0, 3], color: "#404040" },
{ element: "C", position: [-1.4, 0, 2.2], color: "#404040" },
{ element: "C", position: [-1.4, 0, 0.8], color: "#404040" },
{ element: "C", position: [0, 1.5, 4.5], color: "#404040" },
{ element: "C", position: [-1.5, 1.5, 6], color: "#404040" },
{ element: "O", position: [0, 0, 4.5], color: "#ff0000" },
{ element: "O", position: [1.5, 1.5, 4.5], color: "#ff0000" },
{ element: "O", position: [-3, 1.5, 6], color: "#ff0000" },
{ element: "O", position: [-1.5, 3, 6], color: "#ff0000" }
],
bonds: [
{ from: 0, to: 1 }, { from: 1, to: 2 }, { from: 2, to: 3 }, { from: 3, to: 4 },
{ from: 4, to: 5 }, { from: 5, to: 0 }, { from: 3, to: 8 }, { from: 8, to: 6 },
{ from: 6, to: 9 }, { from: 6, to: 7 }, { from: 7, to: 10 }, { from: 7, to: 11 }
],
description: "A widely used pain reliever and anti-inflammatory drug, first synthesized in 1897."
},
{
name: "Caffeine (C₈H₁₀N₄O₂)",
formula: "C8H10N4O2",
category: "pharmaceuticals",
atoms: [
{ element: "N", position: [0, 0, 0], color: "#0000ff" },
{ element: "C", position: [1.4, 0, 0], color: "#404040" },
{ element: "N", position: [2.1, 1.2, 0], color: "#0000ff" },
{ element: "C", position: [1.4, 2.4, 0], color: "#404040" },
{ element: "C", position: [0, 2.4, 0], color: "#404040" },
{ element: "N", position: [-0.7, 1.2, 0], color: "#0000ff" },
{ element: "C", position: [0, 3.8, 0], color: "#404040" },
{ element: "N", position: [1.4, 3.8, 0], color: "#0000ff" },
{ element: "O", position: [2.1, -1.2, 0], color: "#ff0000" },
{ element: "O", position: [-0.7, 4.6, 0], color: "#ff0000" },
{ element: "C", position: [-2.1, 1.2, 0], color: "#404040" },
{ element: "C", position: [2.8, 4.6, 0], color: "#404040" },
{ element: "C", position: [-0.7, -1.2, 0], color: "#404040" }
],
bonds: [
{ from: 0, to: 1 }, { from: 1, to: 2 }, { from: 2, to: 3 }, { from: 3, to: 4 },
{ from: 4, to: 5 }, { from: 5, to: 0 }, { from: 4, to: 6 }, { from: 6, to: 7 },
{ from: 7, to: 3 }, { from: 1, to: 8 }, { from: 6, to: 9 }, { from: 5, to: 10 },
{ from: 7, to: 11 }, { from: 0, to: 12 }
],
description: "A natural stimulant found in coffee, tea, and chocolate, widely consumed worldwide."
},
// Environmental/Atmospheric
{
name: "Ozone (O₃)",
formula: "O3",
category: "environmental",
atoms: [
{ element: "O", position: [0, 0, 0], color: "#ff0000" },
{ element: "O", position: [1.3, 0, 0], color: "#ff0000" },
{ element: "O", position: [0.65, 1.13, 0], color: "#ff0000" }
],
bonds: [{ from: 0, to: 1 }, { from: 1, to: 2 }],
description: "An atmospheric molecule that protects Earth from UV radiation but is toxic at ground level."
},
{
name: "Methyl Chloride (CH₃Cl)",
formula: "CH3Cl",
category: "environmental",
atoms: [
{ element: "C", position: [0, 0, 0], color: "#404040" },
{ element: "Cl", position: [1.78, 0, 0], color: "#00ff00" },
{ element: "H", position: [-0.51, 0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-0.51, -0.89, 0.51], color: "#ffffff" },
{ element: "H", position: [-0.51, 0, -1.03], color: "#ffffff" }
],
bonds: [
{ from: 0, to: 1 }, { from: 0, to: 2 }, { from: 0, to: 3 }, { from: 0, to: 4 }
],
description: "A chlorinated compound that contributes to ozone depletion in the stratosphere."
},
// Additional Important Molecules
{
name: "Hydrogen Peroxide (H₂O₂)",
formula: "H2O2",
category: "simple",
atoms: [
{ element: "O", position: [-0.74, 0, 0], color: "#ff0000" },
{ element: "O", position: [0.74, 0, 0], color: "#ff0000" },
{ element: "H", position: [-1.21, 0.93, 0], color: "#ffffff" },
{ element: "H", position: [1.21, -0.93, 0], color: "#ffffff" }
],
bonds: [{ from: 0, to: 1 }, { from: 0, to: 2 }, { from: 1, to: 3 }],
description: "A strong oxidizing agent used as disinfectant and bleaching agent."
},
{
name: "Nitrous Oxide (N₂O)",
formula: "N2O",
category: "simple",
atoms: [
{ element: "N", position: [-1.13, 0, 0], color: "#0000ff" },
{ element: "N", position: [0, 0, 0], color: "#0000ff" },
{ element: "O", position: [1.19, 0, 0], color: "#ff0000" }
],
bonds: [{ from: 0, to: 1 }, { from: 1, to: 2 }],
description: "Laughing gas, used as anesthetic and greenhouse gas contributing to climate change."
}
];
const CATEGORIES = [
{ value: "all", label: "All Categories", count: MOLECULES.length },
{ value: "simple", label: "Simple Molecules", count: MOLECULES.filter(m => m.category === "simple").length },
{ value: "hydrocarbons", label: "Hydrocarbons", count: MOLECULES.filter(m => m.category === "hydrocarbons").length },
{ value: "aromatics", label: "Aromatics", count: MOLECULES.filter(m => m.category === "aromatics").length },
{ value: "alcohols", label: "Alcohols", count: MOLECULES.filter(m => m.category === "alcohols").length },
{ value: "acids", label: "Acids", count: MOLECULES.filter(m => m.category === "acids").length },
{ value: "biomolecules", label: "Biomolecules", count: MOLECULES.filter(m => m.category === "biomolecules").length },
{ value: "inorganic", label: "Inorganic", count: MOLECULES.filter(m => m.category === "inorganic").length },
{ value: "pharmaceuticals", label: "Pharmaceuticals", count: MOLECULES.filter(m => m.category === "pharmaceuticals").length },
{ value: "environmental", label: "Environmental", count: MOLECULES.filter(m => m.category === "environmental").length }
];
const ThreeCanvas = ({ molecule, isAnimating }) => {
const mountRef = useRef(null);
useEffect(() => {
if (!molecule || !mountRef.current) return;
const currentMount = mountRef.current;
// Scene, Camera, Renderer
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x1e293b); // slate-800
const camera = new THREE.PerspectiveCamera(75, currentMount.clientWidth / currentMount.clientHeight, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(currentMount.clientWidth, currentMount.clientHeight);
currentMount.appendChild(renderer.domElement);
// Lights
const ambientLight = new THREE.AmbientLight(0xffffff, 0.7);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 0.5);
pointLight.position.set(5, 5, 5);
scene.add(pointLight);
// Molecule Group
const moleculeGroup = new THREE.Group();
scene.add(moleculeGroup);
// Create Atoms
molecule.atoms.forEach(atom => {
const geometry = new THREE.SphereGeometry(atom.element === 'H' ? 0.2 : 0.4, 32, 32);
const material = new THREE.MeshStandardMaterial({ color: atom.color });
const sphere = new THREE.Mesh(geometry, material);
sphere.position.set(...atom.position);
moleculeGroup.add(sphere);
});
// Create Bonds
molecule.bonds?.forEach(bond => {
const start = new THREE.Vector3(...molecule.atoms[bond.from].position);
const end = new THREE.Vector3(...molecule.atoms[bond.to].position);
const path = new THREE.LineCurve3(start, end);
const geometry = new THREE.TubeGeometry(path, 1, 0.05, 8, false);
const material = new THREE.MeshStandardMaterial({ color: '#cccccc' });
const mesh = new THREE.Mesh(geometry, material);
moleculeGroup.add(mesh);
});
// Center the molecule
new THREE.Box3().setFromObject(moleculeGroup).getCenter(moleculeGroup.position).multiplyScalar(-1);
// Animation loop
let animationFrameId;
const animate = () => {
animationFrameId = requestAnimationFrame(animate);
if (isAnimating) {
moleculeGroup.rotation.y += 0.005;
moleculeGroup.rotation.x += 0.002;
}
renderer.render(scene, camera);
};
animate();
// Resize handler
const handleResize = () => {
if (!currentMount) return;
camera.aspect = currentMount.clientWidth / currentMount.clientHeight;
camera.updateProjectionMatrix();
renderer.setSize(currentMount.clientWidth, currentMount.clientHeight);
};
window.addEventListener('resize', handleResize);
// Cleanup
return () => {
window.removeEventListener('resize', handleResize);
if (currentMount.contains(renderer.domElement)) {
currentMount.removeChild(renderer.domElement);
}
cancelAnimationFrame(animationFrameId);
};
}, [molecule, isAnimating]);
return <div ref={mountRef} className="w-full h-full" />;
};
export default function MolecularViewer() {
const [selectedMolecule, setSelectedMolecule] = useState(MOLECULES[0]);
const [isAnimating, setIsAnimating] = useState(true);
const [searchTerm, setSearchTerm] = useState("");
const [selectedCategory, setSelectedCategory] = useState("all");
const filteredMolecules = MOLECULES.filter(mol => {
const matchesSearch = mol.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
mol.formula.toLowerCase().includes(searchTerm.toLowerCase());
const matchesCategory = selectedCategory === "all" || mol.category === selectedCategory;
return matchesSearch && matchesCategory;
});
return (
<div className="min-h-screen bg-gradient-to-br from-slate-50 to-purple-50 p-4 md:p-8">
<div className="max-w-7xl mx-auto">
<div className="mb-8">
<div className="flex items-center gap-3 mb-4">
<div className="w-12 h-12 bg-gradient-to-br from-purple-600 to-pink-700 rounded-xl flex items-center justify-center">
<Atom className="w-6 h-6 text-white" />
</div>
<div>
<h1 className="text-3xl font-bold text-slate-900">3D Molecular Database</h1>
<p className="text-slate-600">Explore {MOLECULES.length} molecular structures in interactive 3D space</p>
</div>
</div>
</div>
<div className="grid lg:grid-cols-4 gap-8">
{/* Molecule Library */}
<div className="lg:col-span-1">
<Card className="border-0 shadow-xl bg-white/80 backdrop-blur-sm">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-lg">
<Search className="w-5 h-5 text-purple-600" />
Molecule Library
</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-4">
<Input
placeholder="Search molecules..."
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
className="bg-white"
/>
<div>
<label className="block text-sm font-medium text-slate-700 mb-2">Category</label>
<Select value={selectedCategory} onValueChange={setSelectedCategory}>
<SelectTrigger className="bg-white">
<SelectValue />
</SelectTrigger>
<SelectContent>
{CATEGORIES.map((category) => (
<SelectItem key={category.value} value={category.value}>
{category.label} ({category.count})
</SelectItem>
))}
</SelectContent>
</Select>
</div>
<div className="space-y-2 max-h-96 overflow-y-auto pr-2">
{filteredMolecules.map((molecule, index) => (
<button
key={index}
onClick={() => setSelectedMolecule(molecule)}
className={`w-full text-left p-3 rounded-lg border transition-all duration-200 ${
selectedMolecule?.name === molecule.name
? 'border-purple-500 bg-purple-50'
: 'border-slate-200 hover:border-purple-300 hover:bg-purple-25'
}`}
>
<div className="font-medium text-slate-900 mb-1">
{molecule.name}
</div>
<div className="flex items-center justify-between">
<Badge variant="outline" className="text-xs">
{molecule.formula}
</Badge>
<Badge variant="secondary" className="text-xs capitalize">
{molecule.category}
</Badge>
</div>
</button>
))}
{filteredMolecules.length === 0 && (
<div className="text-center py-8 text-slate-500">
<Search className="w-12 h-12 mx-auto mb-2 opacity-50" />
<p>No molecules found</p>
</div>
)}
</div>
</div>
</CardContent>
</Card>
</div>
{/* Main Viewer */}
<div className="lg:col-span-3">
<Card className="border-0 shadow-xl bg-white/80 backdrop-blur-sm">
<CardHeader>
<div className="flex items-center justify-between flex-wrap gap-4">
<CardTitle className="text-xl">
{selectedMolecule?.name}
</CardTitle>
<div className="flex items-center gap-2">
<Button
variant="outline"
size="icon"
onClick={() => setIsAnimating(!isAnimating)}
title={isAnimating ? "Pause Animation" : "Play Animation"}
>
{isAnimating ? (
<Pause className="w-4 h-4" />
) : (
<Play className="w-4 h-4" />
)}
</Button>
</div>
</div>
</CardHeader>
<CardContent>
<Tabs defaultValue="viewer" className="w-full">
<TabsList className="grid w-full grid-cols-2 mb-6">
<TabsTrigger value="viewer">3D Viewer</TabsTrigger>
<TabsTrigger value="info">Molecule Info</TabsTrigger>
</TabsList>
<TabsContent value="viewer" className="space-y-0">
<div className="h-96 w-full bg-gradient-to-b from-slate-900 to-slate-800 rounded-xl overflow-hidden relative">
<ThreeCanvas molecule={selectedMolecule} isAnimating={isAnimating} />
<div className="absolute top-4 right-4">
<Badge className="bg-purple-600 text-white">
{selectedMolecule?.formula}
</Badge>
</div>
</div>
</TabsContent>
<TabsContent value="info" className="space-y-6">
<div className="grid md:grid-cols-2 gap-6">
<Card className="bg-gradient-to-br from-blue-50 to-indigo-50 border-blue-200">
<CardContent className="p-6">
<div className="flex items-center gap-2 mb-3">
<Info className="w-5 h-5 text-blue-600" />
<h3 className="font-semibold text-blue-900">Molecular Formula</h3>
</div>
<p className="text-2xl font-bold text-blue-800 font-mono">
{selectedMolecule?.formula}
</p>
</CardContent>
</Card>
<Card className="bg-gradient-to-br from-emerald-50 to-teal-50 border-emerald-200">
<CardContent className="p-6">
<div className="flex items-center gap-2 mb-3">
<Atom className="w-5 h-5 text-emerald-600" />
<h3 className="font-semibold text-emerald-900">Atom Count</h3>
</div>
<p className="text-2xl font-bold text-emerald-800">
{selectedMolecule?.atoms.length} atoms
</p>
</CardContent>
</Card>
</div>
<Card className="bg-gradient-to-br from-purple-50 to-pink-50 border-purple-200">
<CardContent className="p-6">
<div className="flex items-center gap-2 mb-3">
<Filter className="w-5 h-5 text-purple-600" />
<h3 className="font-semibold text-purple-900">Category</h3>
</div>
<Badge className="capitalize bg-purple-600 text-white text-lg px-3 py-1">
{selectedMolecule?.category}
</Badge>
</CardContent>
</Card>
<Card className="bg-slate-50 border-slate-200">
<CardHeader>
<CardTitle className="text-lg">Description</CardTitle>
</CardHeader>
<CardContent>
<p className="text-slate-700 leading-relaxed">
{selectedMolecule?.description}
</p>
</CardContent>
</Card>
{selectedMolecule?.atoms && (
<Card className="bg-slate-50 border-slate-200">
<CardHeader>
<CardTitle className="text-lg">Atomic Composition</CardTitle>
</CardHeader>
<CardContent>
<div className="space-y-3">
{Object.entries(
selectedMolecule.atoms.reduce((acc, atom) => {
acc[atom.element] = (acc[atom.element] || 0) + 1;
return acc;
}, {})
).map(([element, count]) => (
<div key={element} className="flex items-center gap-3">
<div
className="w-8 h-8 rounded-full border-2 border-slate-300 flex items-center justify-center text-xs font-bold"
style={{
backgroundColor: selectedMolecule.atoms.find(a => a.element === element)?.color,
color: element === 'H' ? '#000' : '#fff'
}}
>
{element}
</div>
<span className="font-medium text-slate-900">{element}</span>
<span className="text-slate-600">× {count}</span>
</div>
))}
</div>
</CardContent>
</Card>
)}
</TabsContent>
</Tabs>
</CardContent>
</Card>
</div>
</div>
</div>
</div>
);
}