Skip to content

Commit

Permalink
Merge pull request #27 from cycloverid/mkoptimize
Browse files Browse the repository at this point in the history
2.5-3.1x speedup on map generation, fixed memory leaks of plates arra…
  • Loading branch information
ftomassetti committed Sep 24, 2015
2 parents 479b416 + 36eaa95 commit e3a8a4d
Show file tree
Hide file tree
Showing 35 changed files with 1,528 additions and 1,696 deletions.
202 changes: 85 additions & 117 deletions src/bounds.cpp
Original file line number Diff line number Diff line change
@@ -1,144 +1,112 @@
/******************************************************************************
* plate-tectonics, a plate tectonics simulation library
* Copyright (C) 2012-2013 Lauri Viitanen
* Copyright (C) 2014-2015 Federico Tomassetti, Bret Curtis
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see http://www.gnu.org/licenses/
*****************************************************************************/
* plate-tectonics, a plate tectonics simulation library
* Copyright (C) 2012-2013 Lauri Viitanen
* Copyright (C) 2014-2015 Federico Tomassetti, Bret Curtis
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see http://www.gnu.org/licenses/
*****************************************************************************/

#include "bounds.hpp"

Bounds::Bounds(const WorldDimension& worldDimension, const FloatPoint& position,
const Dimension& dimension)
: _worldDimension(worldDimension),
_position(position),
_dimension(dimension)
{
if (_dimension.getWidth() > _worldDimension.getWidth()) {
throw runtime_error("(Bounds::Bounds) Plate is larger than the world containing it");
}
if (_dimension.getHeight() > _worldDimension.getHeight()) {
throw runtime_error("(Bounds::Bounds) Plate is taller than the world containing it");
}
const Dimension& dimension)
: _worldDimension(worldDimension),
_position(position),
_dimension(dimension) {
ASSERT(_dimension.getWidth() <= _worldDimension.getWidth() &&
_dimension.getHeight() <= _worldDimension.getHeight(),
"Bounds are larger than the world containing it");
}

uint32_t Bounds::index(uint32_t x, uint32_t y) const
{
if (x >= _dimension.getWidth()) {
throw runtime_error("Bounds::Index: unvalid x coordinate");
}
if (y >= _dimension.getHeight()) {
throw runtime_error("Bounds::Index: unvalid y coordinate");
}
return y * _dimension.getWidth() + x;
}
uint32_t Bounds::index(uint32_t x, uint32_t y) const {
ASSERT(x < _dimension.getWidth() && y < _dimension.getHeight(),
"Invalid coordinates");
return y * _dimension.getWidth() + x;
}

uint32_t Bounds::area() const
{
return _dimension.getArea();
uint32_t Bounds::area() const {
return _dimension.getArea();
}

uint32_t Bounds::width() const
{
return _dimension.getWidth();
uint32_t Bounds::width() const {
return _dimension.getWidth();
}

uint32_t Bounds::height() const
{
return _dimension.getHeight();
uint32_t Bounds::height() const {
return _dimension.getHeight();
}

uint32_t Bounds::leftAsUint() const
{
p_assert(_position.getX() >= 0, "_position.getX() should be not negative");
return _position.getX();
uint32_t Bounds::leftAsUint() const {
return (uint32_t)_position.getX();
}

uint32_t Bounds::topAsUint() const
{
p_assert(_position.getY() >= 0, "_position.getY() should be not negative");
return _position.getY();
}
uint32_t Bounds::topAsUint() const {
return (uint32_t)_position.getY();
}

uint32_t Bounds::rightAsUintNonInclusive() const
{
return leftAsUint() + width() - 1;
uint32_t Bounds::rightAsUintNonInclusive() const {
return leftAsUint() + width() - 1;
}

uint32_t Bounds::bottomAsUintNonInclusive() const
{
return topAsUint() + height() - 1;
uint32_t Bounds::bottomAsUintNonInclusive() const {
return topAsUint() + height() - 1;
}

bool Bounds::containsWorldPoint(uint32_t x, uint32_t y) const
{
return asRect().contains(x, y);
bool Bounds::containsWorldPoint(uint32_t x, uint32_t y) const {
return asRect().contains(x, y);
}

bool Bounds::isInLimits(float x, float y) const
{
if (x<0) return false;
if (y<0) return false;
uint32_t ux = x;
uint32_t uy = y;
return ux < _dimension.getWidth() && uy < _dimension.getHeight();
bool Bounds::isInLimits(float x, float y) const {
if (x<0) return false;
if (y<0) return false;
uint32_t ux = (uint32_t)x;
uint32_t uy = (uint32_t)y;
return ux < _dimension.getWidth() && uy < _dimension.getHeight();
}

void Bounds::shift(float dx, float dy) {
_position.shift(dx, dy, _worldDimension);
p_assert(_worldDimension.contains(_position), "");
}

void Bounds::grow(int dx, int dy)
{
if (dx<0) throw runtime_error("negative value");
if (dy<0) throw runtime_error("negative value");
_dimension.grow(dx, dy);

if (_dimension.getWidth() > _worldDimension.getWidth()) {
throw runtime_error("(Bounds::grow) Plate is larger than the world containing it");
}
if (_dimension.getHeight() > _worldDimension.getHeight()) {
string s("(Bounds::grow) Plate is taller than the world containing it:");
s += " delta=" + Platec::to_string(dy);
s += " resulting plate height=" + Platec::to_string(_dimension.getHeight());
s += " world height=" + Platec::to_string(_worldDimension.getHeight());
throw runtime_error(s);
}
}

Platec::Rectangle Bounds::asRect() const
{
p_assert(_position.getX() > 0.0f && _position.getY() >= 0.0f, "(Bounds::asRect) Left and top must be positive");
const uint32_t ilft = leftAsUint();
const uint32_t itop = topAsUint();
const uint32_t irgt = ilft + _dimension.getWidth();
const uint32_t ibtm = itop + _dimension.getHeight();

return Platec::Rectangle(_worldDimension, ilft, irgt, itop, ibtm);
}

uint32_t Bounds::getMapIndex(uint32_t* px, uint32_t* py) const
{
return asRect().getMapIndex(px, py);
}

uint32_t Bounds::getValidMapIndex(uint32_t* px, uint32_t* py) const
{
uint32_t res = asRect().getMapIndex(px, py);
if (res == BAD_INDEX) {
throw runtime_error("BAD INDEX found");
}
return res;
_position.shift(dx, dy, _worldDimension);
ASSERT(_worldDimension.contains(_position), "Point not in world!");
}

void Bounds::grow(int dx, int dy) {
ASSERT(dx >= 0 && dy >= 0, "Negative delta is not allowed");
_dimension.grow(dx, dy);

ASSERT(_dimension.getWidth() <= _worldDimension.getWidth(),
"Bounds are larger than the world containing it");
ASSERT(_dimension.getHeight() <= _worldDimension.getHeight(),
"Bounds taller than the world containing it. delta=" + Platec::to_string(dy)
+ " resulting plate height=" + Platec::to_string(_dimension.getHeight())
+ " world height=" + Platec::to_string(_worldDimension.getHeight()));
}

Platec::Rectangle Bounds::asRect() const {
const uint32_t ilft = leftAsUint();
const uint32_t itop = topAsUint();
const uint32_t irgt = ilft + _dimension.getWidth();
const uint32_t ibtm = itop + _dimension.getHeight();

return Platec::Rectangle(_worldDimension, ilft, irgt, itop, ibtm);
}

uint32_t Bounds::getMapIndex(uint32_t* px, uint32_t* py) const {
return asRect().getMapIndex(px, py);
}

uint32_t Bounds::getValidMapIndex(uint32_t* px, uint32_t* py) const {
uint32_t res = asRect().getMapIndex(px, py);
ASSERT(res != BAD_INDEX, "BAD map index found");
return res;
}
111 changes: 10 additions & 101 deletions src/geometry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
* License along with this library; if not, see http://www.gnu.org/licenses/
*****************************************************************************/

#include <math.h>
#include "geometry.hpp"

//
Expand All @@ -38,10 +37,6 @@ int IntPoint::getY() const
return _y;
}

IntPoint operator-(const IntPoint& a, const IntPoint& b) {
return IntPoint(a.getX() - b.getX(), a.getY() - b.getY());
}

//
// FloatPoint
//
Expand All @@ -62,19 +57,17 @@ float FloatPoint::getY() const

void FloatPoint::shift(float dx, float dy, const WorldDimension& _worldDimension)
{
const uint32_t world_width = _worldDimension.getWidth();
_x += dx;
_x += _x > 0 ? 0 : _worldDimension.getWidth();
_x -= _x < _worldDimension.getWidth() ? 0 : _worldDimension.getWidth();
_x += _x > 0 ? 0 : world_width;
_x -= _x < world_width ? 0 : world_width;

const uint32_t world_height = _worldDimension.getHeight();
_y += dy;
_y += _y > 0 ? 0 : _worldDimension.getHeight();
_y -= _y < _worldDimension.getHeight() ? 0 : _worldDimension.getHeight();

p_assert(_worldDimension.contains(*this), "(FloatPoint::shift)");
}
_y += _y > 0 ? 0 : world_height;
_y -= _y < world_height ? 0 : world_height;

IntPoint FloatPoint::toInt() const {
return IntPoint((int)_x, (int)_y);
ASSERT(_worldDimension.contains(*this), "Point not in world!");
}

//
Expand All @@ -91,21 +84,6 @@ Dimension::Dimension(const Dimension& original) :
{
}

uint32_t Dimension::getWidth() const
{
return _width;
}

uint32_t Dimension::getHeight() const
{
return _height;
}

uint32_t Dimension::getArea() const
{
return _width * _height;
}

bool Dimension::contains(const uint32_t x, const uint32_t y) const
{
return (x >= 0 && x < _width && y >= 0 && y < _height);
Expand Down Expand Up @@ -144,24 +122,14 @@ uint32_t WorldDimension::getMax() const
return _width > _height ? _width : _height;
}

uint32_t WorldDimension::xMod(int x) const
{
return (x + _width) % getWidth();
}

uint32_t WorldDimension::yMod(int y) const
{
return (y + _height) % getHeight();
}

uint32_t WorldDimension::xMod(uint32_t x) const
{
return (x + _width) % getWidth();
return (x + _width) % _width;
}

uint32_t WorldDimension::yMod(uint32_t y) const
{
return (y + _height) % getHeight();
return (y + _height) % _height;
}

void WorldDimension::normalize(uint32_t& x, uint32_t& y) const
Expand All @@ -177,9 +145,7 @@ uint32_t WorldDimension::indexOf(const uint32_t x, const uint32_t y) const

uint32_t WorldDimension::lineIndex(const uint32_t y) const
{
if (y<0 || y>=_height){
throw invalid_argument("WorldDimension::line_index: y is not valid");
}
ASSERT(y >= 0 && y < _height, "y is not valid");
return indexOf(0, y);
}

Expand Down Expand Up @@ -213,60 +179,3 @@ uint32_t WorldDimension::largerSize() const
{
return _width > _height ? _width : _height;
}


namespace Platec {

IntVector::IntVector(int x, int y)
: _x(x), _y(y)
{ }

float IntVector::length() const {
float nx = _x;
float ny = _y;
return sqrt(nx * nx + ny * ny);
}

IntVector IntVector::fromDistance(const IntPoint& a, const IntPoint& b){
return IntVector(a.getX() - b.getX(), a.getY() - b.getY());
}

IntVector operator-(const IntVector& a, const IntVector& b) {
return IntVector(a.x() - b.x(), a.y() - b.y());
}

FloatVector IntVector::toUnitVector() const {
return FloatVector(_x/length(), _y/length());
}

bool operator==(const FloatVector& a, const FloatVector& b) {
return a.x() == b.x() && a.y() == b.y();
}

FloatVector::FloatVector(float x, float y)
: _x(x), _y(y)
{ }

IntVector FloatVector::toIntVector() const {
return IntVector((int)_x, (int)_y);
}

FloatVector operator-(const FloatVector& a, const FloatVector& b) {
return FloatVector(a.x() - b.x(), a.y() - b.y());
}

FloatVector operator*(const FloatVector& v, float f) {
return FloatVector(v.x() * f, v.y() * f);
}

float FloatVector::dotProduct(const FloatVector& other) const {
return x() * other.x() + y() * other.y();
}

float FloatVector::length() const {
float nx = _x;
float ny = _y;
return sqrt(nx * nx + ny * ny);
}

}
Loading

0 comments on commit e3a8a4d

Please sign in to comment.