From 0e04a864ce27f3d86e25dec62222774a3dea609c Mon Sep 17 00:00:00 2001 From: Nick Gasson Date: Sat, 27 Feb 2010 15:40:14 +0000 Subject: [PATCH] Disallow raising terrain over track --- include/ITrackSegment.hpp | 8 +++++-- include/Maths.hpp | 10 ++++++++ src/CrossoverTrack.cpp | 5 ++-- src/CurvedTrack.cpp | 48 +++++++++++++++++++++++++++++++++++---- src/Editor.cpp | 4 ++-- src/IterateTrack.cpp | 2 +- src/Map.cpp | 38 +++++++++++++++++++------------ src/Points.cpp | 29 +++++++++++++++++++++-- src/StraightTrack.cpp | 5 ++-- 9 files changed, 120 insertions(+), 29 deletions(-) diff --git a/include/ITrackSegment.hpp b/include/ITrackSegment.hpp index 2105e2b..58302a2 100644 --- a/include/ITrackSegment.hpp +++ b/include/ITrackSegment.hpp @@ -22,7 +22,7 @@ #include "Maths.hpp" #include "IXMLSerialisable.hpp" -#include +#include #include // Types used for specifying track segments @@ -114,7 +114,11 @@ struct ITrackSegment : IXMLSerialisable { // Note that an endpoint is not the same as what is returned // from `nextPosition' - e.g. a straight track that takes up // one tile has a single endpoint which is its origin - virtual void getEndpoints(std::list >& aList) const = 0; + virtual void getEndpoints(vector >& aList) const = 0; + + // Similar to endpoints, the `covers' of a track are the tiles + // which are not endpoints but are underneath the track + virtual void getCovers(vector >& output) const = 0; // Add an exit to this section of track possibly generating // a new track segment diff --git a/include/Maths.hpp b/include/Maths.hpp index 9ab3e86..4005667 100644 --- a/include/Maths.hpp +++ b/include/Maths.hpp @@ -161,10 +161,20 @@ struct Point { return aPoint.x == x && aPoint.y == y; } + bool operator!=(const Point& rhs) const + { + return rhs.x != x || rhs.y != y; + } + Point operator+(const Point& rhs) const { return Point(x + rhs.x, y + rhs.y); } + + bool operator<(const Point& rhs) const + { + return x < rhs.x || y < rhs.y; + } T x, y; }; diff --git a/src/CrossoverTrack.cpp b/src/CrossoverTrack.cpp index 80383b8..14dd454 100644 --- a/src/CrossoverTrack.cpp +++ b/src/CrossoverTrack.cpp @@ -44,7 +44,8 @@ public: double segmentLength(const track::TravelToken& aToken) const; bool isValidDirection(const track::Direction& aDirection) const; track::Connection nextPosition(const track::TravelToken& aToken) const; - void getEndpoints(std::list >& aList) const; + void getEndpoints(vector >& aList) const; + void getCovers(vector >& output) const { } ITrackSegmentPtr mergeExit(const Point& aPoint, const track::Direction& aDirection); track::TravelToken getTravelToken(track::Position aPosition, @@ -171,7 +172,7 @@ CrossoverTrack::nextPosition(const track::TravelToken& aToken) const ("Invalid direction on crossover: " + lexical_cast(aToken.direction)); } -void CrossoverTrack::getEndpoints(std::list >& aList) const +void CrossoverTrack::getEndpoints(vector >& aList) const { aList.push_back(makePoint(myX, myY)); } diff --git a/src/CurvedTrack.cpp b/src/CurvedTrack.cpp index d3413b4..452accf 100644 --- a/src/CurvedTrack.cpp +++ b/src/CurvedTrack.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -46,7 +47,8 @@ public: Connection nextPosition(const track::TravelToken& aToken) const; bool isValidDirection(const Direction& aDirection) const; - void getEndpoints(list >& aList) const; + void getEndpoints(vector >& aList) const; + void getCovers(vector >& output) const; ITrackSegmentPtr mergeExit(const Point& aPoint, const track::Direction& aDirection); @@ -217,7 +219,7 @@ Connection CurvedTrack::nextPosition(const track::TravelToken& aToken) const nextDir); } -void CurvedTrack::getEndpoints(list >& aList) const +void CurvedTrack::getEndpoints(vector >& aList) const { aList.push_back(origin); @@ -233,15 +235,53 @@ void CurvedTrack::getEndpoints(list >& aList) const aList.push_back(makePoint(origin.x + xDelta, origin.y + yDelta)); } +void CurvedTrack::getCovers(vector >& output) const +{ + vector > exits; + getEndpoints(exits); + + const Point& start = exits.at(0); + const Point& finish = exits.at(1); + + Point trueOrigin = + (startAngle == 90 || startAngle == 270) + ? makePoint(finish.x, start.y) + : makePoint(start.x, finish.y); + + set > tmp; + + // A fiddle factor to put the cover tiles in the best location + const float fiddleRadius = static_cast(baseRadius) - 0.5f; + + const float sign = (startAngle == 0 || startAngle == 180) ? 1.0f : -1.0f; + + for (track::Angle angle = startAngle; angle < finishAngle; angle += 5) { + float x = fiddleRadius * sign * cos(degToRad(angle)); + float y = fiddleRadius * sign * sin(degToRad(angle)); + Point p = makePoint(static_cast(x), + static_cast(y)); + + if (abs(p.x) >= baseRadius || abs(p.y) >= baseRadius) + continue; + + Point actual = p + trueOrigin; + + if (actual != start && actual != finish) + tmp.insert(actual); + } + + copy(tmp.begin(), tmp.end(), back_inserter(output)); +} + ITrackSegmentPtr CurvedTrack::mergeExit(const Point& aPoint, const track::Direction& aDirection) { // See if this is already an exit if (isValidDirection(aDirection)) { - list > exits; + vector > exits; getEndpoints(exits); - for (list >::iterator it = exits.begin(); + for (vector >::iterator it = exits.begin(); it != exits.end(); ++it) if (*it == aPoint) return shared_from_this(); diff --git a/src/Editor.cpp b/src/Editor.cpp index 6533d62..894a682 100644 --- a/src/Editor.cpp +++ b/src/Editor.cpp @@ -419,11 +419,11 @@ void Editor::drawDraggedTrack() ITrackSegmentPtr track = makeCurvedTrack(startAngle, endAngle, xlen); track->setOrigin(where.x, where.y); - list > exits; + vector > exits; track->getEndpoints(exits); bool ok = true; - for (list >::iterator it = exits.begin(); + for (vector >::iterator it = exits.begin(); it != exits.end(); ++it) { if (map->isValidTrack(*it)) { warn() << "Cannot place curve here"; diff --git a/src/IterateTrack.cpp b/src/IterateTrack.cpp index 4dd9d73..f6766dc 100644 --- a/src/IterateTrack.cpp +++ b/src/IterateTrack.cpp @@ -52,7 +52,7 @@ TrackIterator iterateTrack(IMapPtr aMap, track::Position aPosition, } // Are we sitting on a station? - typedef list > PointList; + typedef vector > PointList; PointList endpoints; it.track->getEndpoints(endpoints); diff --git a/src/Map.cpp b/src/Map.cpp index 4ac5bfc..0f9a4e8 100644 --- a/src/Map.cpp +++ b/src/Map.cpp @@ -263,11 +263,12 @@ void Map::eraseTile(int x, int y) // We have to be a bit careful since a piece of track has multiple // endpoints - list > endpoints; - tile.track->get()->getEndpoints(endpoints); + vector > covers; + tile.track->get()->getEndpoints(covers); + tile.track->get()->getCovers(covers); - for (list >::iterator it = endpoints.begin(); - it != endpoints.end(); ++it) + for (vector >::iterator it = covers.begin(); + it != covers.end(); ++it) tileAt((*it).x, (*it).y).track.reset(); } @@ -281,12 +282,13 @@ void Map::setTrackAt(const Point& aPoint, ITrackSegmentPtr aTrack) TrackNodePtr node(new TrackNode(aTrack, aPoint.x, aPoint.y)); - // Attach the track node to every endpoint - list > endpoints; - aTrack->getEndpoints(endpoints); + // Attach the track node to every tile it covers + vector > covers; + aTrack->getEndpoints(covers); + aTrack->getCovers(covers); - for (list >::iterator it = endpoints.begin(); - it != endpoints.end(); ++it) { + for (vector >::iterator it = covers.begin(); + it != covers.end(); ++it) { tileAt((*it).x, (*it).y).track = node; } } @@ -753,12 +755,20 @@ void Map::renderSector(IGraphicsPtr aContext, int id, tile.track->setMark(); +#if 0 // Draw the endpoints for debugging - //list > endpoints; - //tile.track->get()->getEndpoints(endpoints); - //for_each(endpoints.begin(), endpoints.end(), - // bind(&Map::highlightTile, this, aContext, placeholders::_1, - // make_tuple(0.9f, 0.1f, 0.1f))); + vector > tiles; + tile.track->get()->getEndpoints(tiles); + for_each(tiles.begin(), tiles.end(), + bind(&Map::highlightTile, this, placeholders::_1, + makeColour(0.9f, 0.1f, 0.1f))); + + tiles.clear(); + tile.track->get()->getCovers(tiles); + for_each(tiles.begin(), tiles.end(), + bind(&Map::highlightTile, this, placeholders::_1, + makeColour(0.4f, 0.7f, 0.1f))); +#endif } // Draw the station, if any diff --git a/src/Points.cpp b/src/Points.cpp index 4bcd6cc..24ec621 100644 --- a/src/Points.cpp +++ b/src/Points.cpp @@ -37,7 +37,8 @@ public: double segmentLength(const track::TravelToken& aToken) const; bool isValidDirection(const track::Direction& aDirection) const; track::Connection nextPosition(const track::TravelToken& aToken) const; - void getEndpoints(std::list >& aList) const; + void getEndpoints(vector >& aList) const; + void getCovers(vector >& output) const; ITrackSegmentPtr mergeExit(const Point& aPoint, const track::Direction& aDirection); track::TravelToken getTravelToken(track::Position aPosition, @@ -499,13 +500,37 @@ Point Points::straightEndpoint() const assert(false); } -void Points::getEndpoints(std::list >& aList) const +void Points::getEndpoints(vector >& aList) const { aList.push_back(makePoint(myX, myY)); aList.push_back(straightEndpoint()); aList.push_back(displacedEndpoint()); } +void Points::getCovers(vector >& output) const +{ + const int reflect = reflected ? -1 : 1; + + if (myAxis == axis::X) { + output.push_back(makePoint(myX + 1, myY + 1*reflect)); + output.push_back(makePoint(myX + 1, myY)); + } + else if (myAxis == -axis::X) { + output.push_back(makePoint(myX - 1, myY - 1*reflect)); + output.push_back(makePoint(myX - 1, myY)); + } + else if (myAxis == axis::Y) { + output.push_back(makePoint(myX - 1*reflect, myY + 1)); + output.push_back(makePoint(myX, myY + 1)); + } + else if (myAxis == -axis::Y) { + output.push_back(makePoint(myX + 1*reflect, myY - 1)); + output.push_back(makePoint(myX, myY - 1)); + } + else + assert(false); +} + ITrackSegmentPtr Points::mergeExit(const Point& aPoint, const track::Direction& aDirection) { diff --git a/src/StraightTrack.cpp b/src/StraightTrack.cpp index edeca76..6fe7663 100644 --- a/src/StraightTrack.cpp +++ b/src/StraightTrack.cpp @@ -46,7 +46,8 @@ public: Vector offsetForDelta(double aDelta) const; Connection nextPosition(const track::TravelToken& aDirection) const; bool isValidDirection(const Direction& aDirection) const; - void getEndpoints(list >& aList) const; + void getEndpoints(vector >& aList) const; + void getCovers(vector >& output) const { } ITrackSegmentPtr mergeExit(const Point& aPoint, const track::Direction& aDirection); @@ -169,7 +170,7 @@ bool StraightTrack::isValidDirection(const Direction& aDirection) const return aDirection == axis::Y || -aDirection == axis::Y; } -void StraightTrack::getEndpoints(list >& aList) const +void StraightTrack::getEndpoints(vector >& aList) const { aList.push_back(origin); } -- 2.39.2