math_util.h revision c2e0dbddbe15c98d52c4786dac06cb8952a8ae6d
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#ifndef CC_BASE_MATH_UTIL_H_ 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define CC_BASE_MATH_UTIL_H_ 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <cmath> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_ptr.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "cc/base/cc_export.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/point3_f.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/point_f.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/size.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/gfx/transform.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace base { class Value; } 192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace gfx { 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class QuadF; 222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Rect; 232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class RectF; 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Transform; 252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class Vector2dF; 262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace cc { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct HomogeneousCoordinate { 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) HomogeneousCoordinate(double new_x, double new_y, double new_z, double new_w) 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : x(new_x), y(new_y), z(new_z), w(new_w) {} 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool ShouldBeClipped() const { return w <= 0.0; } 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::PointF CartesianPoint2d() const { 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (w == 1.0) 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::PointF(x, y); 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // For now, because this code is used privately only by MathUtil, it should 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // never be called when w == 0, and we do not yet need to handle that case. 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(w); 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double inv_w = 1.0 / w; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::PointF(x * inv_w, y * inv_w); 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Point3F CartesianPoint3d() const { 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (w == 1) 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Point3F(x, y, z); 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // For now, because this code is used privately only by MathUtil, it should 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // never be called when w == 0, and we do not yet need to handle that case. 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(w); 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double inv_w = 1.0 / w; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Point3F(x * inv_w, y * inv_w, z * inv_w); 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double x; 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double y; 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double z; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) double w; 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class CC_EXPORT MathUtil { 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public: 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const double kPiDouble; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static const float kPiFloat; 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static double Deg2Rad(double deg) { return deg * kPiDouble / 180.0; } 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static double Rad2Deg(double rad) { return rad * 180.0 / kPiDouble; } 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static float Deg2Rad(float deg) { return deg * kPiFloat / 180.0f; } 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static float Rad2Deg(float rad) { return rad * 180.0f / kPiFloat; } 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static float Round(float f) { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (f > 0.f) ? std::floor(f + 0.5f) : std::ceil(f - 0.5f); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static double Round(double d) { 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (d > 0.0) ? std::floor(d + 0.5) : std::ceil(d - 0.5); 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Background: Existing transform code does not do the right thing in 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // MapRect / MapQuad / ProjectQuad when there is a perspective projection that 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // causes one of the transformed vertices to go to w < 0. In those cases, it 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // is necessary to perform clipping in homogeneous coordinates, after applying 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the transform, before dividing-by-w to convert to cartesian coordinates. 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // These functions return the axis-aligned rect that encloses the correctly 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // clipped, transformed polygon. 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::Rect MapClippedRect(const gfx::Transform& transform, 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Rect rect); 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::RectF MapClippedRect(const gfx::Transform& transform, 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::RectF& rect); 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::RectF ProjectClippedRect(const gfx::Transform& transform, 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::RectF& rect); 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns an array of vertices that represent the clipped polygon. After 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // returning, indexes from 0 to num_vertices_in_clipped_quad are valid in the 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // clipped_quad array. Note that num_vertices_in_clipped_quad may be zero, 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // which means the entire quad was clipped, and none of the vertices in the 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // array are valid. 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static void MapClippedQuad(const gfx::Transform& transform, 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::QuadF& src_quad, 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::PointF clipped_quad[8], 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int* num_vertices_in_clipped_quad); 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::RectF ComputeEnclosingRectOfVertices(gfx::PointF vertices[], 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int num_vertices); 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::RectF ComputeEnclosingClippedRect( 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const HomogeneousCoordinate& h1, 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const HomogeneousCoordinate& h2, 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const HomogeneousCoordinate& h3, 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const HomogeneousCoordinate& h4); 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // NOTE: These functions do not do correct clipping against w = 0 plane, but 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // they correctly detect the clipped condition via the boolean clipped. 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::QuadF MapQuad(const gfx::Transform& transform, 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::QuadF& quad, 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* clipped); 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::PointF MapPoint(const gfx::Transform& transform, 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::PointF point, 1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* clipped); 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::Point3F MapPoint(const gfx::Transform&, 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Point3F&, 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* clipped); 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::QuadF ProjectQuad(const gfx::Transform& transform, 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::QuadF& quad, 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* clipped); 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::PointF ProjectPoint(const gfx::Transform& transform, 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::PointF point, 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool* clipped); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::Vector2dF ComputeTransform2dScaleComponents(const gfx::Transform&, 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) float fallbackValue); 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns the smallest angle between the given two vectors in degrees. 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Neither vector is assumed to be normalized. 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static float SmallestAngleBetweenVectors(gfx::Vector2dF v1, 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Vector2dF v2); 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Projects the |source| vector onto |destination|. Neither vector is assumed 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // to be normalized. 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static gfx::Vector2dF ProjectVector(gfx::Vector2dF source, 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Vector2dF destination); 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Conversion to value. 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static scoped_ptr<base::Value> AsValue(gfx::Size s); 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static scoped_ptr<base::Value> AsValue(gfx::PointF q); 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static scoped_ptr<base::Value> AsValue(gfx::QuadF q); 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Returns a base::Value representation of the floating point value. 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the value is inf, returns max double/float representation. 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static scoped_ptr<base::Value> AsValueSafely(double value); 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static scoped_ptr<base::Value> AsValueSafely(float value); 1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace cc 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif // CC_BASE_MATH_UTIL_H_ 160