VIRTUOS_Playground/VIRTUOS_ExpansionPluginTests/Source/VRExpPluginExample/Private/MoleculeFunctionLIbrary.cpp

62 lines
1.7 KiB
C++
Raw Normal View History

#include "MoleculeFunctionLibrary.h"
#include "Misc/Paths.h"
#include "Misc/FileHelper.h"
bool UMoleculeFunctionLibrary::ParsePDBFromString(const FString& PDBContent, TArray<FAtom>& OutAtoms, TArray<FBond>& OutBonds)
{
OutAtoms.Empty();
OutBonds.Empty();
if (PDBContent.IsEmpty())
{
UE_LOG(LogTemp, Warning, TEXT("ParsePDBFromString: Input string is empty"));
return false;
}
TArray<FString> Lines;
PDBContent.ParseIntoArrayLines(Lines, true);
for (const FString& Line : Lines)
{
if (!Line.StartsWith(TEXT("ATOM")) && !Line.StartsWith(TEXT("HETATM")))
continue;
if (Line.Len() < 54) // At least enough for X, Y, Z
continue;
FAtom Atom;
// Coordinates (columns are 1-indexed in spec)
Atom.Position.X = FCString::Atof(*Line.Mid(30, 8));
Atom.Position.Y = FCString::Atof(*Line.Mid(38, 8));
Atom.Position.Z = FCString::Atof(*Line.Mid(46, 8));
// Element symbol (columns 77-78), fallback to atom name (columns 13-16)
if (Line.Len() >= 78)
Atom.Element = Line.Mid(76, 2).TrimStartAndEnd();
if (Atom.Element.IsEmpty())
Atom.Element = Line.Mid(12, 4).TrimStartAndEnd().Left(1); // fallback
OutAtoms.Add(Atom);
}
// Bond inference: simple distance-based
const float MaxBondDistance = 1.6f; // can tweak for different atom types
for (int32 i = 0; i < OutAtoms.Num(); i++)
{
for (int32 j = i + 1; j < OutAtoms.Num(); j++)
{
if (FVector::Distance(OutAtoms[i].Position, OutAtoms[j].Position) <= MaxBondDistance)
{
FBond Bond;
Bond.AtomIndex1 = i;
Bond.AtomIndex2 = j;
OutBonds.Add(Bond);
}
}
}
UE_LOG(LogTemp, Log, TEXT("Parsed %d atoms and %d bonds from string"), OutAtoms.Num(), OutBonds.Num());
return true;
}