// Implementation of the RoadSegment class // CSE143 Spring '01 // Homework 6 #include "road_segment.h" #include "intersection.h" #include "vehicle.h" #include "gp142display.h" #include #include RoadSegment::RoadSegment() { isec[Entry] = isec[Exit] = NULL; corner[Entry] = corner[Exit] = Position(); cornerSet[Entry] = cornerSet[Exit] = false; // STARTER CODE: initialize to empty. // Add your own code to initialize the queue structure. vehicle = NULL; } RoadSegment::~RoadSegment() { // STARTER CODE: delete the only vehicle on the road, if any. // Add your own code to clean up the queue of vehicles. if (vehicle != NULL) delete vehicle; } // Set the entry or exit corner position for this road segment. // Warning: avoid modifying this method, as it is not straightforward void RoadSegment::setCorner(Position pos, int entryOrExit) { corner[entryOrExit] = pos; cornerSet[entryOrExit] = true; if (cornerSet[Entry] && cornerSet[Exit]) findOrientation(); } // Set the given intersection as the entry or exit of this segment // Precondition: no intersection for that side has been set yet. void RoadSegment::setIntersection(Intersection *isec, int entryOrExit) { this->isec[entryOrExit] = isec; } // Draws the segment, INCLUDING calling draw() for all the vehicles in it. // Precondition: the segment is set up properly. void RoadSegment::draw(GP142Display& gp) { gp.drawRectangle(corner[Entry].getX(), corner[Entry].getY(), corner[Exit].getX(), corner[Exit].getY(), Black, 0); gp.drawRectangle(corner[Entry].getX(), corner[Entry].getY(), corner[Exit].getX(), corner[Exit].getY(), White, 1); if (vehicle != NULL) vehicle->draw(gp); } // Advances cars that are currently in the segment void RoadSegment::tick() { // STARTER CODE: advance the only vehicle 1 pixel at a time. // Add your own code to advance all vehicles and avoid collisions. if (vehicle != NULL) { if (!isVehicleWaiting(vehicle)) vehicle->advance(1); } } // Add a vehicle at the entry to the segment. // Precondition: vehicle != NULL, and canEnqueue(vehicle). void RoadSegment::enqueue(Vehicle *vehicle) { assert (canEnqueue()); // STARTER CODE: segment can only have one vehicle at a time. // Add your own code to enqueue on the vehicle queue. this->vehicle = vehicle; vehicle->setPosition(entryPosition()); vehicle->turn(orientation); } // Returns true iff a vehicle can be enqueued at this time. // The result might be invalidated if non-const operations are done. bool RoadSegment::canEnqueue() const { // STARTER CODE: segment can only have one vehicle at a time. // Add your own code to do this for the queue implementation. return (vehicle == NULL); } // Remove the first vehicle from the head of the queue. // Returns a pointer to the dequeued vehicle, NULL if none. Vehicle *RoadSegment::dequeue() { // STARTER CODE: return the only vehicle, if any, and remove it. // Add your own code to dequeue the vehicle queue. Vehicle *temp = vehicle; vehicle = NULL; return temp; } // Returns true if there's a vehicle waiting to enter the intersection bool RoadSegment::vehicleWaiting() const { if (vehicle == NULL) return false; return isVehicleWaiting(vehicle); } // Returns true if the specified vehicle is waiting at the intersection. // Precondition: v != NULL. bool RoadSegment::isVehicleWaiting(Vehicle *v) const { assert (v != NULL); Position pos = v->getPosition(); switch (orientation) { case North: return (pos.getY() >= corner[Exit].getY()); case East: return (pos.getX() >= corner[Exit].getX()); case South: return (pos.getY() <= corner[Exit].getY()); case West: return (pos.getX() <= corner[Exit].getX()); } // for compiler's benefit: should never get here! return false; } // Compute the orientation given the corners. // Precondition: both corners were set. // Warning: avoid modifying this method, as it is not straightforward void RoadSegment::findOrientation() { assert (cornerSet[Entry] && cornerSet[Exit]); int dx = corner[Exit].getX() - corner[Entry].getX(); int dy = corner[Exit].getY() - corner[Entry].getY(); if ((dx > 0) && (dy > 0)) { orientation = East; } else if ((dx > 0) && (dy < 0)) { orientation = South; } else if ((dx < 0) && (dy < 0)) { orientation = West; } else { orientation = North; } } // Return the center of the road at its entry point. // This is the first position for newly enqueued vehicles. Position RoadSegment::entryPosition() const { if (orientation == North || orientation == South) { int x = (corner[Entry].getX() + corner[Exit].getX()) / 2; return Position(x, corner[Entry].getY()); } else { int y = (corner[Entry].getY() + corner[Exit].getY()) / 2; return Position(corner[Entry].getX(), y); } }