26#define EIGEN_DONT_VECTORIZE
29#include <Eigen/Geometry>
31#include <nlohmann/json.hpp>
33using json = nlohmann::json;
36#define M_PI 3.14159265358979323846
39#include "rxdock/Config.h"
41extern std::istream &eatSeps(std::istream &is);
59 inline Coord() : xyz(0.0, 0.0, 0.0) {}
62 inline Coord(
double x1,
double y1,
double z1) : xyz(x1, y1, z1) {}
65 inline Coord(Eigen::Vector3d xyz1) : xyz(xyz1) {}
71 inline Coord(
const Coord &coord) { xyz = coord.xyz; }
86 inline Coord &operator=(
const double &d) {
92 inline void operator+=(
const Coord &coord) { xyz += coord.xyz; }
95 inline void operator+=(
const double &d) { xyz += xyz.Constant(d); }
98 inline void operator-=(
const Coord &coord) { xyz -= coord.xyz; }
101 inline void operator-=(
const double &d) { xyz -= xyz.Constant(d); }
104 inline void operator*=(
const double &d) { xyz *= d; }
107 inline void operator/=(
const double &d) { xyz /= d; }
114 friend std::ostream &operator<<(std::ostream &s,
const Coord &coord) {
115 return s <<
"(" << coord.xyz(0) <<
"," << coord.xyz(1) <<
","
116 << coord.xyz(2) <<
")";
132 friend std::istream &operator>>(std::istream &s,
Coord &coord) {
133 double x = 0, y = 0, z = 0;
145 s.clear(std::ios_base::badbit);
155 coord =
Coord(x, y, z);
160 inline friend bool operator==(
const Coord &coord1,
const Coord &coord2) {
161 return coord1.xyz == coord2.xyz;
165 inline friend bool operator!=(
const Coord &coord1,
const Coord &coord2) {
166 return coord1.xyz != coord2.xyz;
170 inline friend bool operator>(
const Coord &coord1,
const Coord &coord2) {
171 return (coord1.xyz.array() > coord2.xyz.array()).all();
175 inline friend bool operator>=(
const Coord &coord1,
const Coord &coord2) {
176 return (coord1.xyz.array() >= coord2.xyz.array()).all();
180 inline friend bool operator<(
const Coord &coord1,
const Coord &coord2) {
181 return (coord1.xyz.array() < coord2.xyz.array()).all();
185 inline friend bool operator<=(
const Coord &coord1,
const Coord &coord2) {
186 return (coord1.xyz.array() <= coord2.xyz.array()).all();
190 inline friend Coord operator+(
const Coord &coord1,
const Coord &coord2) {
191 return Coord(coord1.xyz + coord2.xyz);
195 inline friend Coord operator+(
const Coord &coord1,
double d) {
196 return Coord(coord1.xyz + coord1.xyz.Constant(d));
200 inline friend Coord operator+(
double d,
const Coord &coord1) {
201 return Coord(coord1.xyz.Constant(d) + coord1.xyz);
205 inline friend Coord operator-(
const Coord &coord1,
const Coord &coord2) {
206 return Coord(coord1.xyz - coord2.xyz);
210 inline friend Coord operator-(
const Coord &coord1,
double d) {
211 return Coord(coord1.xyz - coord1.xyz.Constant(d));
215 inline friend Coord operator-(
double d,
const Coord &coord1) {
216 return Coord(coord1.xyz.Constant(d) - coord1.xyz);
220 inline friend Coord operator-(
const Coord &coord) {
221 return Coord(-coord.xyz);
233 inline friend Coord operator*(
const Coord &coord,
const double &d) {
234 return Coord(coord.xyz * d);
238 inline friend Coord operator*(
const double &d,
const Coord &coord) {
239 return Coord(d * coord.xyz);
243 inline friend Coord operator*(
const Coord &coord1,
const Coord &coord2) {
244 return Coord(coord1.xyz.array() * coord2.xyz.array());
248 inline friend Coord operator/(
const Coord &coord,
const double &d) {
249 return Coord(coord.xyz / d);
252 friend void to_json(json &j,
const Coord &c) {
253 j = json{c.xyz(0), c.xyz(1), c.xyz(2)};
256 friend void from_json(
const json &j,
Coord &c) {
257 j.at(0).get_to(c.xyz(0));
258 j.at(1).get_to(c.xyz(1));
259 j.at(2).get_to(c.xyz(2));
269 inline double Length2()
const {
return xyz.squaredNorm(); }
272 inline double Length()
const {
return xyz.norm(); }
277 inline Coord Unit()
const {
279 return (l > 0) ? *
this / l : *
this;
283 inline Coord Cross(
const Coord &v2)
const {
return Coord(xyz.cross(v2.xyz)); }
286 inline double Dot(
const Coord &v2)
const {
return xyz.dot(v2.xyz); }
295typedef std::vector<Coord> CoordList;
296typedef CoordList::iterator CoordListIter;
297typedef CoordList::const_iterator CoordListConstIter;
304typedef std::map<unsigned int, Coord> UIntCoordMap;
305typedef UIntCoordMap::iterator UIntCoordMapIter;
306typedef UIntCoordMap::const_iterator UIntCoordMapConstIter;
317inline double Length2(
const Vector &v1) {
return v1.Length2(); }
320inline double Length2(
const Coord &c1,
const Coord &c2) {
321 return Length2(c2 - c1);
325inline double Length(
const Vector &v1) {
return v1.Length(); }
328inline double Length(
const Coord &c1,
const Coord &c2) {
329 return Length(c2 - c1);
334inline Vector Unit(
const Vector &v1) {
return v1.Unit(); }
337inline Vector Cross(
const Vector &v11,
const Vector &v2) {
338 return v11.Cross(v2);
342inline double Dot(
const Vector &v1,
const Vector &v2) {
return v1.Dot(v2); }
345inline double Angle(
const Vector &v1,
const Vector &v2) {
347 double d1d2 = v1.Length() * v2.Length();
350 double cos_theta = v1.Dot(v2) / d1d2;
351 double sin_theta = (v1.Cross(v2)).Length() / d1d2;
354 double theta = std::atan2(sin_theta, cos_theta);
355 return theta * 180.0 / M_PI;
359inline double Angle(
const Coord &coord1,
const Coord &coord2,
360 const Coord &coord3) {
362 return Angle(coord1 - coord2, coord3 - coord2);
367inline double Dihedral(
const Vector &v1,
const Vector &v2,
const Vector &v3) {
369 Vector A = v1.Cross(v2);
370 Vector B = v2.Cross(v3);
371 Vector C = v2.Cross(A);
373 double rA = A.Length();
374 double rB = B.Length();
375 double rC = C.Length();
377 double cos_phi = A.Dot(B) / (rA * rB);
378 double sin_phi = C.Dot(B) / (rC * rB);
380 double phi = -std::atan2(sin_phi, cos_phi);
381 return phi * 180.0 / M_PI;
385inline double Dihedral(
const Coord &c1,
const Coord &c2,
const Coord &c3,
388 return Dihedral(c1 - c2, c2 - c3, c3 - c4);
396inline double ExtractXCoord(
const Coord &c) {
return c.xyz(0); }
397inline double ExtractYCoord(
const Coord &c) {
return c.xyz(1); }
398inline double ExtractZCoord(
const Coord &c) {
return c.xyz(2); }
401inline Coord Min(
const Coord &coord1,
const Coord &coord2) {
402 return Coord(coord1.xyz.array().min(coord2.xyz.array()));
406inline Coord Max(
const Coord &coord1,
const Coord &coord2) {
407 return Coord(coord1.xyz.array().max(coord2.xyz.array()));
412inline Coord Min(
const CoordList &cl) {
413 std::vector<double> cx, cy, cz;
415 std::transform(cl.begin(), cl.end(), std::back_inserter(cx), ExtractXCoord);
416 std::transform(cl.begin(), cl.end(), std::back_inserter(cy), ExtractYCoord);
417 std::transform(cl.begin(), cl.end(), std::back_inserter(cz), ExtractZCoord);
419 return Coord(*(std::min_element(cx.begin(), cx.end())),
420 *(std::min_element(cy.begin(), cy.end())),
421 *(std::min_element(cz.begin(), cz.end())));
426inline Coord Max(
const CoordList &cl) {
427 std::vector<double> cx, cy, cz;
429 std::transform(cl.begin(), cl.end(), std::back_inserter(cx), ExtractXCoord);
430 std::transform(cl.begin(), cl.end(), std::back_inserter(cy), ExtractYCoord);
431 std::transform(cl.begin(), cl.end(), std::back_inserter(cz), ExtractZCoord);
433 return Coord(*(std::max_element(cx.begin(), cx.end())),
434 *(std::max_element(cy.begin(), cy.end())),
435 *(std::max_element(cz.begin(), cz.end())));
439inline Coord GetCenterOfAtomicMass(
const CoordList &coordList) {
441 com = std::accumulate(coordList.begin(), coordList.end(), com);
443 return coordList.empty() ? com : com /
static_cast<double>(coordList.size());