3 // (C) 1997-2007 Christopher J. Madsen
4 // (C) 2019 James Hammons
6 // GUEmap is licensed under either version 2 of the GPL, or (at your option)
7 // any later version. See LICENSE file for details.
12 #include "mathconstants.h"
18 // end1: The corner of room1 where this edge begins
19 // end2: The corner of room2 where this edge ends
20 // room1: The room where this edge begins
21 // room2: The room where this edge ends
23 // The type of exit this is from room1
24 // The etSpecial codes are only used with type1
26 // The type2 of exit this is from room2
28 MapEdge::MapEdge(): room1(0), room2(0), end1(rcNone), end2(rcNone), type1(0), type2(0)
32 MapEdge::MapEdge(RoomNum r1, RoomNum r2, EdgeType t1, EdgeType t2, RoomCorner e1, RoomCorner e2): room1(r1), room2(r2), end1(e1), end2(e2), type1(t1), type2(t2)
36 void MapEdge::Clear(void)
44 // Actually swap the rooms for this edge
46 void MapEdge::Swap(void)
61 bool MapEdge::HasRoom(RoomNum r)
63 if ((room1 != r) && (room2 != r))
70 // Return the MapEdge but with the RoomNums, EdgeTypes, & RoomCorners swapped
72 MapEdge MapEdge::Swapped(void) const
74 // Not sure why, but MapDoc::findEdge() keeps the etObstructed on room 1 for some reason...
75 return MapEdge(room2, room1, type2 | (type1 & etObstructed), type1 & ~etObstructed, end2, end1);
83 // Bitmask of RoomFlags constants:
84 // rfBorder: Room has a border (default)
85 // rfCorner: Room is a corner connector (no name, one grid square)
87 // The position of the top left corner of the room
88 // Given in logical MM_HIMETRIC coordinates.
90 // The name of the room.
92 MapRoom::MapRoom(): flags(0)
96 MapRoom::MapRoom(const MapRoom & o)
101 MapRoom & MapRoom::operator=(const MapRoom & source)
106 flags = source.flags;
110 QRect MapRoom::getRect(void)
113 (flags & rfCorner ? QSize(gridX, gridY) : QSize(roomWidth, roomHeight)));
116 QRect MapRoom::getTranslatedRect(QPoint t)
118 return QRect(pos + t,
119 (flags & rfCorner ? QSize(gridX, gridY) : QSize(roomWidth, roomHeight)));
122 QPoint MapRoom::GetCenter(void)
126 ? QPoint(gridX / 2, gridY / 2)
127 : QPoint(roomWidth / 2, roomHeight / 2)));
130 RoomFlags MapRoom::isCorner() const
132 return (flags & rfCorner);
135 bool MapRoom::operator!=(const MapRoom & mr) const
150 // Miscellaneous functions:
151 //--------------------------------------------------------------------
153 // Trim whitespace from left of string:
155 void trimLeft(string & s)
157 StrIdx p = s.find_first_not_of("\n\r\t ");
164 // Trim whitespace from right of string:
166 void trimRight(string & s)
168 StrIdx p = s.find_last_not_of("\n\r\t ");
175 // Consolidates action creation from a multi-step process to a single-step one.
177 QAction * CreateAction(QString name, QString tooltip,
178 QString statustip, QIcon icon, QKeySequence key, bool checkable/*= false*/, QObject * parent/*= 0*/)
180 QAction * action = new QAction(icon, name, parent);
181 action->setToolTip(tooltip);
182 action->setStatusTip(statustip);
183 action->setShortcut(key);
184 action->setCheckable(checkable);
190 // This is essentially the same as the previous function, but this allows more
191 // than one key sequence to be added as key shortcuts.
193 QAction * CreateAction(QString name, QString tooltip,
194 QString statustip, QIcon icon, QKeySequence key1, QKeySequence key2,
195 bool checkable/*= false*/, QObject * parent/*= 0*/)
197 QAction * action = new QAction(icon, name, parent);
198 action->setToolTip(tooltip);
199 action->setStatusTip(statustip);
200 QList<QKeySequence> keyList;
201 keyList.append(key1);
202 keyList.append(key2);
203 action->setShortcuts(keyList);
204 action->setCheckable(checkable);
210 // Miscellaneous geometrical helper functions
212 double Magnitude(QPointF p)
214 return sqrt((p.x() * p.x()) + (p.y() * p.y()));
217 QPointF UnitVector(QPointF p)
219 double magnitude = Magnitude(p);
222 return QPointF(0, 0);
224 return QPointF(p.x() / magnitude, p.y() / magnitude);
227 double Angle(QPointF p)
229 double angle = atan2(p.y(), p.x());
237 double Angle(QPoint p)
239 double angle = atan2((double)p.y(), (double)p.x());
247 double Dot(QPointF a, QPointF b)
249 return (a.x() * b.x()) + (a.y() * b.y());
252 double Determinant(QPointF a, QPointF b)
254 return (a.x() * b.y()) - (b.x() * a.y());
257 // Returns the parameter of a point in space to this vector. If the parameter
258 // is between 0 and 1, the normal of the vector to the point is on the vector.
259 double ParameterOfLineAndPoint(QPointF tail, QPointF head, QPointF point)
261 // Geometric interpretation:
262 // The parameterized point on the vector lineSegment is where the normal of
263 // the lineSegment to the point intersects lineSegment. If the pp < 0, then
264 // the perpendicular lies beyond the 1st endpoint. If pp > 1, then the
265 // perpendicular lies beyond the 2nd endpoint.
267 QPointF lineSegment = head - tail;
268 double magnitude = Magnitude(lineSegment);
269 QPointF pointSegment = point - tail;
270 double t = Dot(lineSegment, pointSegment) / (magnitude * magnitude);