Skip to content

Commit

Permalink
Cleanup math utilities (#2183)
Browse files Browse the repository at this point in the history
* Clean up and add docs in geom.h

* Clean up and document 2d rotation functions

* Fixup tests using FLT_EPSILON
  • Loading branch information
matteblair committed Aug 8, 2020
1 parent 96dae37 commit 0709ee8
Show file tree
Hide file tree
Showing 10 changed files with 147 additions and 209 deletions.
2 changes: 1 addition & 1 deletion core/src/labels/curvedLabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ void CurvedLabel::addVerticesToMesh(ScreenTransform& _transform, const glm::vec2

for (int i = 0; i < 4; i++) {

vertexPosition[i] = p + glm::i16vec2{rotateBy(glm::vec2(quad.quad[i].pos) - origin, rotation)};
vertexPosition[i] = p + glm::i16vec2{rotate2d(glm::vec2(quad.quad[i].pos) - origin, rotation)};

if (!visible &&
vertexPosition[i].x > min.x &&
Expand Down
2 changes: 1 addition & 1 deletion core/src/labels/label.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void Label::enterState(const State& _state, float _alpha) {
}

void Label::setAlpha(float _alpha) {
m_alpha = CLAMP(_alpha, 0.0, 1.0);
m_alpha = clamp01(_alpha);
}

void Label::resetState() {
Expand Down
6 changes: 2 additions & 4 deletions core/src/labels/spriteLabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,9 @@ bool SpriteLabel::updateScreenTransform(const glm::mat4& _mvp, const ViewState&

// Rotate in clockwise order on the ground plane
if (m_options.angle != 0.f) {
glm::vec2 rotation(cos(DEG_TO_RAD * m_options.angle),
sin(DEG_TO_RAD * m_options.angle));

glm::vec2 rotation = rotation2dDeg(m_options.angle);
for (size_t i = 0; i < 4; i++) {
positions[i] = rotateBy(positions[i], rotation);
positions[i] = rotate2d(positions[i], rotation);
}
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/labels/textLabel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ bool TextLabel::updateScreenTransform(const glm::mat4& _mvp, const ViewState& _v

m_screenCenter = screenPosition;

PointTransform(_transform).set(screenPosition + rotateBy(offset, rotation), rotation);
PointTransform(_transform).set(screenPosition + rotate2d(offset, rotation), rotation);

return true;
}
Expand Down Expand Up @@ -231,7 +231,7 @@ void TextLabel::addVerticesToMesh(ScreenTransform& _transform, const glm::vec2&

if (rotate) {
for (int i = 0; i < 4; i++) {
vertexPosition[i] = sp + glm::i16vec2{rotateBy(quad.quad[i].pos, rotation)};
vertexPosition[i] = sp + glm::i16vec2{rotate2d(quad.quad[i].pos, rotation)};
}
} else {
for (int i = 0; i < 4; i++) {
Expand Down
11 changes: 5 additions & 6 deletions core/src/style/pointStyleBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,12 @@ void PointStyleBuilder::addLabel(const Point& _point, const glm::vec4& _quad, Te

if (_params.labelOptions.angle != 0.f) {
// Rotate the sprite icon quad vertices in clockwise order
glm::vec2 rotation(cos(-DEG_TO_RAD * _params.labelOptions.angle),
sin(-DEG_TO_RAD * _params.labelOptions.angle));
glm::vec2 rotation = rotation2dDeg(-_params.labelOptions.angle);

v0 = rotateBy(v0, rotation);
v1 = rotateBy(v1, rotation);
v2 = rotateBy(v2, rotation);
v3 = rotateBy(v3, rotation);
v0 = rotate2d(v0, rotation);
v1 = rotate2d(v1, rotation);
v2 = rotate2d(v2, rotation);
v3 = rotate2d(v3, rotation);
}

m_quads.push_back({{
Expand Down
4 changes: 2 additions & 2 deletions core/src/style/textStyleBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ bool TextStyleBuilder::addStraightTextLabels(const Line& _line, float _labelWidt
dir2 = (p1 - p2) / segmentLength;

glm::vec2 pp = glm::vec2(_line[j-1]);
float d = sqPointSegmentDistance(pp, p0, p2);
float d = pointSegmentDistanceSq(pp, p0, p2);
if (d > tolerance) { break; }

if ((glm::length2(dir1 + dir2) < sqDirLimit) ||
Expand Down Expand Up @@ -439,7 +439,7 @@ void TextStyleBuilder::addCurvedTextLabels(const Line& _line, const TextStyle::P
// Take cross product of direction (unit-) vectors of the current
// and next segment. The magnitude of the cross product is the sine
// angle between dir1 and dir2.
float angle = crossProduct(dir1, dir2);
float angle = perpDotProduct(dir1, dir2);

if (std::abs(angle) > flipTolerance) {
if (lastAngle > 0) {
Expand Down
3 changes: 1 addition & 2 deletions core/src/util/builders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,7 @@ void Builders::buildPolygon(const Polygon& _polygon, float _height, PolygonBuild
glm::vec3 coord(p.x, p.y, _height);

if (_ctx.useTexCoords) {
glm::vec2 uv(mapValue(coord.x, min.x, max.x, 0., 1.),
mapValue(coord.y, min.y, max.y, 1., 0.));
glm::vec2 uv(mapRange01(coord.x, min.x, max.x), mapRange01(coord.y, max.y, min.y));

_ctx.addVertex(coord, glm::vec3(0.0, 0.0, 1.0), uv);
} else {
Expand Down
89 changes: 14 additions & 75 deletions core/src/util/geom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,70 +2,14 @@

#include "glm/gtx/norm.hpp"
#include <cmath>
#include <limits>

namespace Tangram {

float mapValue(const float& _value, const float& _inputMin, const float& _inputMax, const float& _outputMin,
const float& _outputMax, bool _clamp) {
if (fabs(_inputMin - _inputMax) < std::numeric_limits<float>::epsilon()) { return _outputMin; } else {
float outVal = ((_value - _inputMin) / (_inputMax - _inputMin) * (_outputMax - _outputMin) + _outputMin);

if (_clamp) {
if (_outputMax < _outputMin) {
if (outVal < _outputMax) {
outVal = _outputMax;
} else if (outVal > _outputMin) {
outVal = _outputMin;
}
} else {
if (outVal > _outputMax) {
outVal = _outputMax;
} else if (outVal < _outputMin) {
outVal = _outputMin;
}
}
}
return outVal;
float mapRange01(float value, float inputMin, float inputMax) {
if (inputMin == inputMax) {
return value > inputMin ? 1 : 0;
}
}

float angleBetweenPoints(const glm::vec2& _p1, const glm::vec2& _p2) {
glm::vec2 p1p2 = _p2 - _p1;
p1p2 = glm::normalize(p1p2);
return (float)atan2(p1p2.x, -p1p2.y);
}

float sqPointSegmentDistance(const glm::vec2& _p, const glm::vec2& _a, const glm::vec2& _b) {

float dx = _b.x - _a.x;
float dy = _b.y - _a.y;

float x = _a.x;
float y = _a.y;

float d = dx * dx + dy * dy;

if (d != 0) {
// project point onto segment
float t = ((_p.x - _a.x) * dx + (_p.y - _a.y) * dy) / d;
if (t > 1) {
x = _b.x;
y = _b.y;
} else if (t > 0) {
x += dx * t;
y += dy * t;
}
}

dx = _p.x - x;
dy = _p.y - y;

return dx * dx + dy * dy;
}

float pointSegmentDistance(const glm::vec2& _p, const glm::vec2& _a, const glm::vec2& _b) {
return sqrt(sqPointSegmentDistance(_p, _a, _b));
return clamp01((value - inputMin) / (inputMax - inputMin));
}

glm::vec2 worldToScreenSpace(const glm::mat4& mvp, const glm::vec4& worldPosition, const glm::vec2& screenSize, bool& behindCamera) {
Expand All @@ -76,28 +20,23 @@ glm::vec2 worldToScreenSpace(const glm::mat4& mvp, const glm::vec4& worldPositio
return screenPosition;
}

// square distance from a point <_p> to a segment <_p1,_p2>
// http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
//
float sqSegmentDistance(const glm::vec2& _p, const glm::vec2& _p1, const glm::vec2& _p2) {
glm::vec2 d(_p2 - _p1);
float lengthSq = glm::length2(d);

float pointSegmentDistanceSq(const glm::vec2& p, const glm::vec2& a, const glm::vec2& b) {
// http://stackoverflow.com/questions/849211/shortest-distance-between-a-point-and-a-line-segment
glm::vec2 segment(b - a);
float lengthSq = glm::length2(segment);
if (lengthSq != 0) {

float t = glm::dot(_p - _p1, d) / lengthSq;

float t = glm::dot(p - a, segment) / lengthSq;
if (t > 1) {
return glm::length2(_p - _p2);
return glm::length2(p - b);
} else if (t > 0) {
return glm::length2(_p - (_p1 + d * t));
return glm::length2(p - (a + segment * t));
}
}
return glm::length2(_p - _p1);
return glm::length2(p - a);
}

bool isPowerOfTwo(int _value) {
return (_value & (_value - 1)) == 0;
float pointSegmentDistance(const glm::vec2& p, const glm::vec2& a, const glm::vec2& b) {
return sqrt(pointSegmentDistanceSq(p, a, b));
}

}
Loading

0 comments on commit 0709ee8

Please sign in to comment.