1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
|
// $Id$
//
// Copyright (C) 2003-2006 Rational Discovery LLC
//
// @@ All Rights Reserved @@
// This file is part of the RDKit.
// The contents are covered by the terms of the BSD license
// which is included in the file license.txt, found at the root
// of the RDKit source tree.
//
#include <RDGeneral/Invariant.h>
#include <cstring>
#include "Transform.h"
#include "Transform2D.h"
#include <math.h>
#include "point.h"
namespace RDGeom {
void Transform2D::setToIdentity() {
unsigned int i, id;
double *data = d_data.get();
memset(static_cast<void *>(data), 0, d_dataSize * sizeof(double));
for (i = 0; i < DIM_2D; i++) {
id = i * (DIM_2D + 1);
data[id] = 1.0;
}
}
void Transform2D::TransformPoint(Point2D &pt) const {
double x, y;
double *data = d_data.get();
x = data[0] * pt.x + data[1] * pt.y + data[2];
y = data[3] * pt.x + data[4] * pt.y + data[5];
pt.x = x;
pt.y = y;
}
void Transform2D::SetTranslation(const Point2D &pt) {
unsigned int i = DIM_2D - 1;
double *data = d_data.get();
data[i] = pt.x;
i += DIM_2D;
data[i] = pt.y;
i += DIM_2D;
data[i] = 1.0;
i += DIM_2D;
}
void Transform2D::SetTransform(const Point2D &pt, double angle) {
this->setToIdentity();
Transform2D trans1;
trans1.SetTranslation(-pt);
double *data = d_data.get();
// set the rotation
data[0] = cos(angle);
data[1] = -sin(angle);
data[3] = sin(angle);
data[4] = cos(angle);
(*this) *= trans1;
// translation back to the orignal coordinate
Transform2D trans2;
trans2.SetTranslation(pt);
trans2 *= (*this);
// now combine them
this->assign(trans2);
}
void Transform2D::SetTransform(const Point2D &ref1, const Point2D &ref2,
const Point2D &pt1, const Point2D &pt2) {
// compute the angle between the two vectors
Point2D rvec = ref2 - ref1;
Point2D pvec = pt2 - pt1;
double dp = rvec.dotProduct(pvec);
double lp = (rvec.length()) * (pvec.length());
if (lp <= 0.0) {
this->setToIdentity();
return;
}
double cval = dp / lp;
if (cval < -1.0) {
cval = -1.0;
} else if (cval > 1.0) {
cval = 1.0;
}
double ang = acos(cval);
// figure out if we have to do clock wise or anti clock wise rotation
double cross = (pvec.x) * (rvec.y) - (pvec.y) * (rvec.x);
if (cross < 0.0) {
ang *= -1.0;
}
this->setToIdentity();
// set the rotation
double *data = d_data.get();
data[0] = cos(ang);
data[1] = -sin(ang);
data[3] = sin(ang);
data[4] = cos(ang);
// apply this rotation to pt1 and compute the translation
Point2D npt1 = pt1;
this->TransformPoint(npt1);
data[DIM_2D - 1] = ref1.x - npt1.x;
data[2 * DIM_2D - 1] = ref1.y - npt1.y;
}
}
RDGeom::Transform2D operator*(const RDGeom::Transform2D &t1,
const RDGeom::Transform2D &t2) {
RDGeom::Transform2D res;
RDNumeric::multiply(t1, t2, res);
return res;
};
|