📄 intersection.cs
字号:
using System;
using System.Collections;
using System.Drawing;
namespace WindowsApplication2
{
/// <summary>
/// Intersection objects represent real intersections,
/// they are critical to the simulation
/// </summary>
[Serializable]
struct ThruStreet
{//Basic struct to encapsulate each thru street
public int seg1;
public int seg2;
public int type,offset,timeGreen;
}
[Serializable]
public class Intersection
{
public const int UNCONTROLLED = -3; //Constants used for return values
public const int DEAD_END = -2;
public const int IS_STOP = -1;
public const int IS_LIGHT = 0;
public const int LIGHT_GREEN = 1;
public const int LIGHT_RED = 2;
private ArrayList streetSegs; //All segments leading into the intersection
private ArrayList thruSts; //ThruStreets formed from streetSegs
private Point location; //Intersection's position on the map
private int cycleTime; //Traffic Light's cycle time
private bool analyzed; //Whether thruSts have been identified
public Intersection(Point loc, int Connection)
{
location = loc;
thruSts = new ArrayList();
streetSegs = new ArrayList();
streetSegs.Add(Connection);
analyzed = false;
cycleTime = 100;
}
public int findSeg(CityMap myMap, int intID)
{//returns the ID of the segment which connects this Intersection to the ID provided
for (int i=0;i<streetSegs.Count;i++)
{
MapSeg toCheck = myMap.getSegment((int)streetSegs[i]);
if (toCheck.From_Intersection == intID || toCheck.To_Intersection == intID)
return (int)streetSegs[i];
}
return -1;
}
public bool makeStop (int idx)
{//Converts the ThruStreet at idx to a stop sign
ThruStreet toChange = (ThruStreet)thruSts[idx];
toChange.type = IS_STOP;
toChange.offset = 0;
toChange.timeGreen = 0;
thruSts[idx] = toChange;
return true;
}
public bool makeDeadEnd (int idx)
{//Converts the ThruStreet at idx to a dead end
ThruStreet toChange = (ThruStreet)thruSts[idx];
toChange.type = DEAD_END;
toChange.offset = 0;
toChange.timeGreen = 0;
thruSts[idx] = toChange;
return true;
}
public bool makeUncontrolled (int idx)
{//Converts the ThruStreet at idx to an uncontrolled intersection
ThruStreet toChange = (ThruStreet)thruSts[idx];
toChange.type = UNCONTROLLED;
toChange.offset = 0;
toChange.timeGreen = 0;
thruSts[idx] = toChange;
return true;
}
public bool makeLight (int idx, int adjust,int gTime)
{//Converts the ThruStreet at idx to a traffic light
ThruStreet toChange = (ThruStreet)thruSts[idx];
toChange.type = IS_LIGHT;
toChange.offset = adjust % cycleTime;
toChange.timeGreen = gTime;
thruSts[idx] = toChange;
return true;
}
public void addConnection (int SegID)
{
streetSegs.Add(SegID);
}
public bool checkConnection (int segID)
{//Debug only, ensures connections have been properly made
for (int i=0; i<streetSegs.Count; i++)
{
if ((int)streetSegs[i] == segID)
return true;
}
return false;
}
public void drawIsolated(Graphics g, CityMap myMap, Scaler miniScale)
{//Draws the intersection by itself (used in both intersection helper forms)
int MXX = int.MinValue;
int MXY = int.MinValue;
int MNX = int.MaxValue;
int MNY = int.MaxValue;
ArrayList pointToDraw = new ArrayList();
ArrayList infoStr = new ArrayList();
Point curr;
for (int i=0;i<streetSegs.Count;i++)
{
int segID = (int)streetSegs[i];
MapSeg toAdd = myMap.getSegment(segID);
if (Distance(toAdd.from,this.getPoint) > Distance (toAdd.to,this.getPoint))
curr = toAdd.from;
else
curr = toAdd.to;
if (curr.X > MXX)
MXX = curr.X;
if (curr.X < MNX)
MNX = curr.X;
if (curr.Y > MXY)
MXY = curr.Y;
if (curr.Y < MNY)
MNY = curr.Y;
pointToDraw.Add(curr);
infoStr.Add("Segment "+segID+": "+toAdd.StreetName);
}
miniScale.setRange(MXX,MXY,MNX,MNY);
miniScale.calculate();
for (int i=0; i<pointToDraw.Count; i++)
{
Pen p = new Pen (Color.White,2.0f);
PointF toDraw = miniScale.translate((Point)pointToDraw[i]);
g.DrawLine(p,toDraw,miniScale.translate(this.getPoint));
toDraw.X *= 0.75f;
toDraw.Y *= 0.75f;
toDraw.Y -= 8.0f * i;
g.DrawString((string)infoStr[i], new Font("Times New Roman",8),
new SolidBrush(Color.Red),toDraw);
}
}
public bool isThru (int segID1, int segID2)
{//Boolean true if the two IDs form a ThruStreet, false otherwise
for (int i=0; i<thruSts.Count; i++)
{
if (((ThruStreet)thruSts[i]).seg1 == segID1 && ((ThruStreet)thruSts[i]).seg2 == segID2)
return true;
else if (((ThruStreet)thruSts[i]).seg1 == segID2 && ((ThruStreet)thruSts[i]).seg2 == segID1)
return true;
}
return false;
}
public int canGo(int segID,int time)
{//1 if green light or uncontrolled, 0 if stop sign, and -1 if impassible
for (int i=0; i<thruSts.Count; i++)
{
if (((ThruStreet)thruSts[i]).seg1 == segID || ((ThruStreet)thruSts[i]).seg2 == segID)
{
int state = this.getState(i,time);
if (state == UNCONTROLLED || state == LIGHT_GREEN)
return 1;
else if (state == LIGHT_RED)
return -1;
else
return 0;
}
}
throw(new MissingMemberException("Segment not found by canGo"));
}
public Point getPoint
{
get {return location;}
set {location = value;}
}
public ArrayList getConnections
{
get {return streetSegs;}
}
public bool IsAnalyzed
{
get {return analyzed;}
}
public ArrayList getThruSts
{
get {return thruSts;}
}
public int getState (int idx, int time)
{//Returns intersection type (or light state if it is a traffic light
ThruStreet toCheck;
try {toCheck = (ThruStreet)thruSts[idx];}
catch {return IS_STOP;} //If there are no ThruStreets Established
if (toCheck.type != IS_LIGHT)
return toCheck.type;
else if ((time + toCheck.offset)%cycleTime < toCheck.timeGreen)
return LIGHT_GREEN;
else
return LIGHT_RED;
}
public int getCycle
{
get {return cycleTime;}
}
public int analyze(CityMap myMap)
{//Sets thruStreet properties correctly
ThruStreet toAdd = new ThruStreet();
switch (this.getConnections.Count)
{
case 1:
toAdd.seg1 = (int)this.getConnections[0];
toAdd.seg2 = -1;
toAdd.type = DEAD_END;
thruSts.Add(toAdd);
analyzed = true;
return 0;
case 2:
toAdd.seg1 = (int)this.getConnections[0];
toAdd.seg2 = (int)this.getConnections[1];
toAdd.type = UNCONTROLLED;
thruSts.Add(toAdd);
analyzed = true;
return 0;
default:
thruSts=findThru(myMap, this.getConnections.Count/2);
analyzed = true;
return 0;
}
}
private double Distance(Point a, Point b)
{
double xdiff = a.X - b.X;
double ydiff = a.Y - b.Y;
return Math.Sqrt(xdiff * xdiff + ydiff * ydiff);
}
private ArrayList findThru (CityMap myMap, int numReq)
{//Identifies ThruStreets from the list of street segments
ArrayList toReturn = new ArrayList();
Point midPoint = this.getPoint;
int num = this.getConnections.Count;
int[] used = new int[num];
for (int i=0; i<num;i++)
{
if (used[i] == 0)
{
Point p1 = myMap.getSegment((int)getConnections[i]).from;
if (Distance (p1,midPoint) < Distance (myMap.getSegment((int)getConnections[i]).to,midPoint))
p1 = myMap.getSegment((int)getConnections[i]).to;
for (int j=i+1; j<num;j++)
{
if (used[j]==0)
{
Point p2 = myMap.getSegment((int)getConnections[j]).from;
if (Distance (p2,midPoint) < Distance (myMap.getSegment((int)getConnections[j]).to,midPoint))
p2 = myMap.getSegment((int)getConnections[j]).to;
double d1 = Distance (p1,p2);
double d2 = Distance (p1,midPoint) + Distance (midPoint, p2);
double ratio = d1/d2;
bool streetNames = (myMap.getSegment((int)getConnections[j]).StreetName == myMap.getSegment((int)getConnections[i]).StreetName)
&& (myMap.getSegment((int)getConnections[j]).StreetName != MapSeg.DEF_ST_NAME);
if ((ratio >= 0.9 && ratio <= 1.1) || streetNames)
{//Two segments are a through street if they are roughly straight or have the same name
used[i] = 1;
used[j] = 1;
ThruStreet found = new ThruStreet();
found.seg1 = (int)getConnections[i];
found.seg2 = (int)getConnections[j];
found.type = IS_STOP;
toReturn.Add(found);
break;
}
}
}
}
}
for (int i=0;i<num;i++)
{
if (used[i] == 0)
{
ThruStreet found = new ThruStreet();
found.seg1 = (int)getConnections[i];
found.seg2 = -1;
found.type = IS_STOP;
toReturn.Add(found);
}
}
return toReturn;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -