MCPcopy Create free account
hub / github.com/NatronGitHub/Natron / movePointToTriangle

Method movePointToTriangle

Gui/QtColorTriangle.cpp:1097–1200  ·  view source on GitHub ↗

! \internal \a a, \a b and \a c are corner points of an equilateral triangle. (\a x,\a y) is an arbitrary point inside or outside this triangle. If (x,y) is inside the triangle, this function returns the double point (x,y). Otherwise, the intersection of the perpendicular projection of (x,y) onto the closest triangle edge is returned, unless this intersection is outs

Source from the content-addressed store, hash-verified

1095 Yes, it's trigonometry.
1096*/
1097QPointF QtColorTriangle::movePointToTriangle(double x, double y, const Vertex &a,
1098 const Vertex &b, const Vertex &c) const
1099{
1100 // Let v1A be the vector from (x,y) to a.
1101 // Let v2A be the vector from a to b.
1102 // Find the angle alphaA between v1A and v2A.
1103 double v1xA = x - a.point.x();
1104 double v1yA = y - a.point.y();
1105 double v2xA = b.point.x() - a.point.x();
1106 double v2yA = b.point.y() - a.point.y();
1107 double vpA = vprod(v1xA, v1yA, v2xA, v2yA);
1108 double cosA = vpA / (vlen(v1xA, v1yA) * vlen(v2xA, v2yA));
1109 double alphaA = acos(cosA);
1110
1111 // Let v1B be the vector from x to b.
1112 // Let v2B be the vector from b to c.
1113 double v1xB = x - b.point.x();
1114 double v1yB = y - b.point.y();
1115 double v2xB = c.point.x() - b.point.x();
1116 double v2yB = c.point.y() - b.point.y();
1117 double vpB = vprod(v1xB, v1yB, v2xB, v2yB);
1118 double cosB = vpB / (vlen(v1xB, v1yB) * vlen(v2xB, v2yB));
1119 double alphaB = acos(cosB);
1120
1121 // Let v1C be the vector from x to c.
1122 // Let v2C be the vector from c back to a.
1123 double v1xC = x - c.point.x();
1124 double v1yC = y - c.point.y();
1125 double v2xC = a.point.x() - c.point.x();
1126 double v2yC = a.point.y() - c.point.y();
1127 double vpC = vprod(v1xC, v1yC, v2xC, v2yC);
1128 double cosC = vpC / (vlen(v1xC, v1yC) * vlen(v2xC, v2yC));
1129 double alphaC = acos(cosC);
1130
1131 // Find the radian angles between the (1,0) vector and the points
1132 // A, B, C and (x,y). Use this information to determine which of
1133 // the edges we should project (x,y) onto.
1134 double angleA = angleAt(a.point, contentsRect());
1135 double angleB = angleAt(b.point, contentsRect());
1136 double angleC = angleAt(c.point, contentsRect());
1137 double angleP = angleAt(QPointF(x, y), contentsRect());
1138
1139 // If (x,y) is in the a-b area, project onto the a-b vector.
1140 if (angleBetweenAngles(angleP, angleA, angleB)) {
1141 // Find the distance from (x,y) to a. Then use the slope of
1142 // the a-b vector with this distance and the angle between a-b
1143 // and a-(x,y) to determine the point of intersection of the
1144 // perpendicular projection from (x,y) onto a-b.
1145 double pdist = sqrt(qsqr(x - a.point.x()) + qsqr(y - a.point.y()));
1146
1147 // the length of all edges is always > 0
1148 double p0x = a.point.x() + ((b.point.x() - a.point.x()) / vlen(v2xB, v2yB)) * cos(alphaA) * pdist;
1149 double p0y = a.point.y() + ((b.point.y() - a.point.y()) / vlen(v2xB, v2yB)) * cos(alphaA) * pdist;
1150
1151 // If (x,y) is above the a-b line, which basically means it's
1152 // outside the triangle, then return its projection onto a-b.
1153 if (pointAbovePoint(x, y, p0x, p0y, a.point.x(), a.point.y(), b.point.x(), b.point.y())) {
1154 // If the projection is "outside" a, return a. If it is

Callers

nothing calls this directly

Calls 12

vprodFunction · 0.85
vlenFunction · 0.85
angleBetweenAnglesFunction · 0.85
qsqrFunction · 0.85
pointAbovePointFunction · 0.85
pointInLineFunction · 0.85
QPointFClass · 0.70
acosFunction · 0.50
sqrtFunction · 0.50
cosFunction · 0.50
xMethod · 0.45
yMethod · 0.45

Tested by

no test coverage detected