Skip to content

Commit

Permalink
Removed unused scalar.cpp.
Browse files Browse the repository at this point in the history
Updated and extended documentation.
Removed vector*<type>::less in favor of replay::array_less.
Added bounding_rectangle_algorithm to find the minimal-area bounding box of a 2D point set.
Renamed math::near to math::fuzzy_equals and math::near_zero to math::fuzzy_zero
Removed some superfluous circle construction functions (construct_sphere, construct_circle, construct_circumcircle). This can be done using equisphere.
  • Loading branch information
marius.elvert committed Aug 9, 2010
1 parent 29c389c commit 1455a55
Show file tree
Hide file tree
Showing 28 changed files with 632 additions and 685 deletions.
1 change: 1 addition & 0 deletions build/msvc100/replay-test.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\test\math_test.cpp" />
<ClCompile Include="..\..\test\minibox_test.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="replay.vcxproj">
Expand Down
5 changes: 4 additions & 1 deletion build/msvc100/replay-test.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\..\..\test\math_test.cpp">
<ClCompile Include="..\..\test\math_test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\test\minibox_test.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
Expand Down
1 change: 1 addition & 0 deletions build/msvc100/replay.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@
<ClInclude Include="..\..\include\replay\matrix2.hpp" />
<ClInclude Include="..\..\include\replay\matrix3.hpp" />
<ClInclude Include="..\..\include\replay\matrix4.hpp" />
<ClInclude Include="..\..\include\replay\bounding_rectangle.hpp" />
<ClInclude Include="..\..\include\replay\minimal_sphere.hpp" />
<ClInclude Include="..\..\include\replay\pixbuf.hpp" />
<ClInclude Include="..\..\include\replay\pixbuf_io.hpp" />
Expand Down
3 changes: 3 additions & 0 deletions build/msvc100/replay.vcxproj.filters
Original file line number Diff line number Diff line change
Expand Up @@ -137,5 +137,8 @@
<ClInclude Include="..\..\include\replay\pixbuf_io.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\include\replay\bounding_rectangle.hpp">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
204 changes: 157 additions & 47 deletions docs/config.doxygen

Large diffs are not rendered by default.

9 changes: 5 additions & 4 deletions include/replay/aabb.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Copyright (c) 2010 Marius Elvert

namespace replay {

/** An iso-box in \f$R^3\f$.
/** An iso-box in \f$\mathbb{R}^3\f$.
Represents the intersection of intervals on the 3 principal axes.
\ingroup Math
*/
Expand All @@ -45,12 +45,13 @@ class aabb :

public:
/** Classification relative to a plane.
\see classify
*/
enum clsfctn
{
negative, /**< all points have a negative distance. */
positive, /**< all points have a positive distance. */
spanning /**< the points have mixed signs in their distances. */
negative, /**< All points have a negative distance to the plane. */
positive, /**< All points have a positive distance to the plane. */
spanning /**< The points have mixed signs in their distances to the plane, so the box intersects the plane. */
};
aabb( );
explicit aabb( const float extends );
Expand Down
259 changes: 259 additions & 0 deletions include/replay/bounding_rectangle.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
/*
replay
Software Library
Copyright (c) 2010 Marius Elvert
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef replay_bounding_rectangle_hpp
#define replay_bounding_rectangle_hpp

#include <memory>
#include <replay/vector2.hpp>
#include <replay/matrix2.hpp>
#include <replay/vector_math.hpp>

namespace replay {

/** Compute a minimal-area bounding rectangle of a 2D convex hull using a rotating calipers algorithm.
This algorithm runs in linear time.
*/
class bounding_rectangle_algorithm
{
public:
bounding_rectangle_algorithm( const vector2f* hull, std::size_t n )
: hull(hull),n(n)
{
// Get an initial box and the extrema
initial_extrema();

// Start with no rotation
current.u.set(1.f,0.f);

// Check all possible configurations
float min_area=compute_current_size();
best=current;

for ( std::size_t i=1; i<n; ++i )
{
rotate_smallest_angle();

// Only rotate a maximum of 90 degrees
if( current.u[0] <= 0.f )
break;

float area = compute_current_size();

// Did we find a better one?
if ( area < min_area )
{
min_area = area;
best = current;
}
}
}

/** Return the matrix used to transform into box coordinates.
*/
const matrix2 get_matrix() const
{
const matrix2 result(
best.u[0], best.u[1],
-best.u[1], best.u[0] );

return result;
}

const vector2f& get_min() const
{
return best.min;
}

const vector2f& get_max() const
{
return best.max;
}


private:

static inline vector2f rotated_left( const vector2f& x )
{
return vector2f( -x[1], x[0] );
}

inline vector2f get_edge( std::size_t i ) const
{
return hull[(i+1)%n]-hull[i];
}

inline void rotate_smallest_angle()
{
float ra,ta,la,ba;
const float zero_deg = 1.f - 0.0001f;

// Move along colinear edges
vector2f t = current.u;
while ( (ba=dot( t, normalized(get_edge(bottom)))) >= zero_deg )
bottom = (bottom+1)%n;

t = rotated_left( current.u );
while ( (ra=dot( t, normalized(get_edge(right)))) >= zero_deg )
right = (right+1)%n;

t = rotated_left( t );
while ( (ta=dot( t, normalized(get_edge(top)))) >= zero_deg)
top = (top+1)%n;

t = rotated_left( t );
while ( (la=dot( t, normalized(get_edge(left)))) >= zero_deg )
left = (left+1)%n;

// Find the smallest angle, which is the greatest cosine
std::size_t s = 0;
float m = ba;

if ( ra > m ) { s=1; m=ra; }
if ( ta > m ) { s=2; m=ta; }
if ( la > m ) { s=3; m=la; }

switch( s )
{
case 0:
t = normalized(get_edge(bottom));
current.u = t;
break;
case 1:

t = normalized(get_edge(right));
current.u.set( t[1],-t[0] );
break;
case 2:
t = normalized(get_edge(top));
current.u = -t;
break;
case 3:
t = normalized(get_edge(left));
current.u.set( -t[1], t[0] );
break;
}
}

inline float compute_current_size()
{
const vector2f& u(current.u);
// phi is defined by the matrix:
// u[0] -u[1]
// u[1] u[0]

const vector2f& l(hull[left]);
const vector2f& b(hull[bottom]);

current.min.set(
l[0]*u[0]+l[1]*u[1], // x component of phi(P[Left])
-b[0]*u[1]+b[1]*u[0] // y component of phi(P[Bottom])
);

// Likewise for right and top
const vector2f& r(hull[right]);
const vector2f& t(hull[top]);

current.max.set(
r[0]*u[0]+r[1]*u[1],
-t[0]*u[1]+t[1]*u[0]
);

float dx = current.max[0]-current.min[0];
float dy = current.max[1]-current.min[1];

return dx*dy;
}

inline void initial_extrema()
{
left = right = top = bottom = 0;

// Find an initial bounding box and the extrema
for ( std::size_t i=1; i<n; ++i )
{
float x = hull[i][0];
float y = hull[i][1];

// Check for a new x
if ( x < hull[left][0] )
left = i;
else if ( x > hull[right][0] )
right = i;
else
{
if ( x == hull[left][0] && y < hull[left][1] )
left = i;

else if ( x == hull[right][0] && y > hull[right][1] )
right = 1;
}

// Check for new y
if ( y < hull[bottom][1] )
bottom = i;
else if ( y > hull[top][1] )
top = i;
else
{
if ( y == hull[bottom][1] && x > hull[bottom][0] )
bottom = i;

else if ( y == hull[top][1] && x < hull[top][0] )
top = i;
}
}
}

// The convex hull
const vector2f* hull;
std::size_t n;

struct box_type {
// box
vector2f min;
vector2f max;

// rotation
vector2f u;
};

box_type current;
box_type best;

// Current extrema
std::size_t top;
std::size_t bottom;
std::size_t left;
std::size_t right;

// Selected edge
std::size_t selected_edge;
};

}

#endif // replay_bounding_rectangle_hpp
5 changes: 4 additions & 1 deletion include/replay/box_packer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,10 @@ Copyright (c) 2010 Marius Elvert
namespace replay
{

/** 2d box packer.
/** A box packer for 2-dimensions.
This algorithm can be used to position a set of axis-aligned rectangles in the plane,
so that they do not overlap and that all rectangles together need only a small bounding box.
It can be used to generate texture atlases.
This uses a first fit packing algorithm.
*/
class box_packer :
Expand Down
2 changes: 2 additions & 0 deletions include/replay/byte_color.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ namespace replay {
class byte_color4
{
public:
/** 8-bit unsigned integer.
*/
typedef unsigned char byte;

/** 32-bit unsigned integer.
Expand Down
15 changes: 8 additions & 7 deletions include/replay/math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,25 +119,26 @@ namespace math {
/** return true if the value is within a treshold of zero.
\ingroup Math
*/
inline bool near_zero( const float value, const float epsilon )
inline bool fuzzy_zero( const float value, const float epsilon )
{
return abs( value ) < epsilon;
return abs(value) < epsilon;
}

/** return true if the value is within a treshold of zero.
\ingroup Math
*/
inline bool near_zero( const float value )
inline bool fuzzy_zero( const float value )
{
return abs( value ) < default_epsilon;
return abs(value) < default_epsilon;
}

/** return true if a is within a treshold of b.
/** Return true if a is within a treshold of b.
This is used to compare floating point numbers.
\ingroup Math
*/
inline bool near( const float a, const float b )
inline bool fuzzy_equals( const float a, const float b, const float epsilon=default_epsilon )
{
return abs( a - b ) < default_epsilon;
return abs(a-b) < epsilon;
}

/** check if the value is in the range. borders count as in.
Expand Down
Loading

0 comments on commit 1455a55

Please sign in to comment.