Compare commits
	
		
			1 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| aad4ce9375 | 
							
								
								
									
										65
									
								
								src/Tour.cpp
									
									
									
									
									
								
							
							
						
						
									
										65
									
								
								src/Tour.cpp
									
									
									
									
									
								
							| @@ -116,6 +116,71 @@ void Tour::insertNearest(Point p) { | ||||
|     nearest->next = newNode; | ||||
| } | ||||
|  | ||||
| enum class Orientation { COLLINEAR, CLOCKWISE, COUNTER_CLOCKWISE }; | ||||
|  | ||||
| // I'm not going to pretend that I came up with this on my own. | ||||
| // The description for the algorithms is found both in the | ||||
| // linear algebra course, and on this wiki | ||||
| // https://en.wikipedia.org/w/index.php?title=Line-line_intersection&oldid=1229564037 | ||||
|  | ||||
| // Calculate the calcOrientation of the triplet (p, q, r) | ||||
| inline Orientation calcOrientation(const Point &p, const Point &q, const Point &r) { | ||||
|     int val = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y); | ||||
|  | ||||
|     if (val == 0) | ||||
|         return Orientation::COLLINEAR; | ||||
|     return (val > 0) ? Orientation::CLOCKWISE : Orientation::COUNTER_CLOCKWISE; | ||||
| } | ||||
| // True if q lies on the segment p-r | ||||
| inline bool isOnSegment(const Point &p, const Point &q, const Point &r) { | ||||
|     return (q.x <= std::max(p.x, r.x) && q.x >= std::min(p.x, r.x) && | ||||
|             q.y <= std::max(p.y, r.y) && q.y >= std::min(p.y, r.y)); | ||||
| } | ||||
| // Check if the two line segments p1q1 and p2q2 intersect | ||||
| bool doesPointsIntersect(const Point &p1, const Point &q1, const Point &p2, | ||||
|                      const Point &q2) { | ||||
|     Orientation o1 = calcOrientation(p1, q1, p2); | ||||
|     Orientation o2 = calcOrientation(p1, q1, q2); | ||||
|     Orientation o3 = calcOrientation(p2, q2, p1); | ||||
|     Orientation o4 = calcOrientation(p2, q2, q1); | ||||
|  | ||||
|     // General case: line segments intersect if they have different orientations | ||||
|     if (o1 != o2 && o3 != o4) | ||||
|         return true; | ||||
|  | ||||
|     // Special cases | ||||
|     // p1, q1, p2 are collinear and p2 lies on segment p1q1 | ||||
|     if (o1 == Orientation::COLLINEAR && isOnSegment(p1, p2, q1)) | ||||
|         return true; | ||||
|     // p1, q1, q2 are collinear and q2 lies on segment p1q1 | ||||
|     if (o2 == Orientation::COLLINEAR && isOnSegment(p1, q2, q1)) | ||||
|         return true; | ||||
|     // p2, q2, p1 are collinear and p1 lies on segment p2q2 | ||||
|     if (o3 == Orientation::COLLINEAR && isOnSegment(p2, p1, q2)) | ||||
|         return true; | ||||
|     // p2, q2, q1 are collinear and q1 lies on segment p2q2 | ||||
|     if (o4 == Orientation::COLLINEAR && isOnSegment(p2, q1, q2)) | ||||
|         return true; | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| bool Tour::pointsCross(Point &p1, Point &p2) { | ||||
|     if (m_startNode == nullptr || m_startNode->next == m_startNode) | ||||
|         return false; | ||||
|     Node *n1 = m_startNode, *n2 = m_startNode->next; | ||||
|     do { | ||||
|         Point &q1 = n1->point, &q2 = n2->point; | ||||
|         if (doesPointsIntersect(p1, p2, q1, q2)) | ||||
|             return true; | ||||
|  | ||||
|         n1 = n2; | ||||
|         n2 = n2->next; | ||||
|     } while (n1 != m_startNode); | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| void Tour::insertSmallest(Point p) { | ||||
|     if (m_startNode == nullptr) { | ||||
|         m_startNode = new Node(p); | ||||
|   | ||||
| @@ -27,6 +27,8 @@ public: | ||||
|  | ||||
| private: | ||||
|     Node* m_startNode; | ||||
|  | ||||
|     bool pointsCross(Point &p1, Point &p2); | ||||
| }; | ||||
|  | ||||
| #endif // TOUR_H | ||||
|   | ||||
		Reference in New Issue
	
	Block a user