/*#####################################################################################################################
#####################################################################################################################
#####################################################################################################################*/#include<algorithm>#include<set>#include<string>#include<vector>#include<stack>#include<iostream>#include<unordered_map>#include<fstream>#include<vector>#include<fstream>#include<sstream>//#include <bits/stdc++.h>usingnamespace std;// A point in 2D planestructPoint{double x, y;};// A line segment with left as Point// with smaller x value and right with// larger x value.structSegment{
Point left, right;/* Segment add(Point left, Point right) {
}*/};// An event for sweep line algorithm// An event has a point, the position// of point (whether left or right) and// index of point in the original input// array of segments.structEvent{double x, y;bool isLeft;int index;Event(double x,double y,bool l,int i):x(x),y(y),isLeft(l),index(i){}// This is for maintaining the order in set.booloperator<(const Event& e)const{if(y == e.y)return x < e.x;return y < e.y;}};// Given three collinear points p, q, r, the function checks if// point q lies on line segment 'pr'boolonSegment(Point p, Point q, Point r){if(q.x <=max(p.x, r.x)&& q.x >=min(p.x, r.x)&&
q.y <=max(p.y, r.y)&& q.y >=min(p.y, r.y))returntrue;returnfalse;}// To find orientation of ordered triplet (p, q, r).// The function returns following values// 0 --> p, q and r are collinear// 1 --> Clockwise// 2 --> Counterclockwiseintorientation(Point p, Point q, Point r){// See https://www.geeksforgeeks.org/orientation-3-ordered-points/// for details of below formula.double val =(q.y - p.y)*(r.x - q.x)-(q.x - p.x)*(r.y - q.y);if(val ==0)return0;// collinearreturn(val >0)?1:2;// clock or counterclock wise}// The main function that returns true if line segment 'p1q1'// and 'p2q2' intersect.booldoIntersect(Segment s1, Segment s2){
Point p1 = s1.left, q1 = s1.right, p2 = s2.left, q2 = s2.right;// Find the four orientations needed for general and// special casesint o1 =orientation(p1, q1, p2);int o2 =orientation(p1, q1, q2);int o3 =orientation(p2, q2, p1);int o4 =orientation(p2, q2, q1);// General caseif(o1 != o2 && o3 != o4)returntrue;// Special Cases// p1, q1 and p2 are collinear and p2 lies on segment p1q1if(o1 ==0&&onSegment(p1, p2, q1))returntrue;// p1, q1 and q2 are collinear and q2 lies on segment p1q1if(o2 ==0&&onSegment(p1, q2, q1))returntrue;// p2, q2 and p1 are collinear and p1 lies on segment p2q2if(o3 ==0&&onSegment(p2, p1, q2))returntrue;// p2, q2 and q1 are collinear and q1 lies on segment p2q2if(o4 ==0&&onSegment(p2, q1, q2))returntrue;returnfalse;// Doesn't fall in any of the above cases}// Find predecessor of iterator in s.
set<Event>::iterator pred(set<Event>& s, set<Event>::iterator it){return it == s.begin()? s.end():--it;}// Find successor of iterator in s.
set<Event>::iterator succ(set<Event>& s, set<Event>::iterator it){return++it;}doubledeterminant(double v1,double v2,double v3,double v4){return(v1 * v4 - v2 * v3);}
Point intersectionaxis(Point p1, Point q1, Point p2, Point q2){
Point respoint;double delta =determinant( q1.x- p1.x, p2.x - q2.x, q1.y - p1.y, p2.y - q2.y);if(delta <=(1e-6)&& delta >=-(1e-6)){
respoint.x= p1.x;
respoint.y = p1.y;}double namenda =determinant(p2.x - p1.x, p2.x - q2.x, p2.y - p1.y, p2.y - q2.y)/ delta;if(namenda >1|| namenda <0){
respoint.x = p1.x;
respoint.y = p1.y;}double miu =determinant(q1.x - p1.x, p2.x - p1.x, q1.y - p1.y, p2.y - p1.y)/ delta;if(miu >1|| miu <0){
respoint.x = p1.x;
respoint.y = p1.y;}
respoint.x = p1.x + namenda *(q1.x - p1.x);
respoint.y = p1.y + namenda *(q1.y - p1.y);return respoint;}// Returns true if any two lines intersect.intisIntersect(Segment arr[],int n){
unordered_map<string,int> mp;// to note the pair for which intersection is checked already// Pushing all points to a vector of events
vector<Event> e;for(int i =0; i < n;++i){
e.push_back(Event(arr[i].left.x, arr[i].left.y,true, i));
e.push_back(Event(arr[i].right.x, arr[i].right.y,false, i));}// Sorting all events according to x coordinate.sort(e.begin(), e.end(),[](Event& e1, Event& e2){return e1.x < e2.x;});// For storing active segments.
set<Event> s;int ans =0;// Traversing through sorted pointsfor(int i =0; i <2* n; i++){
Event curr = e[i];int index = curr.index;// If current point is left of its segmentif(curr.isLeft){// Get above and below pointsauto next = s.lower_bound(curr);auto prev =pred(s, next);// Check if current point intersects with// any of its adjacentbool flag =false;if(next != s.end()&&doIntersect(arr[next->index], arr[index])){
string s =to_string(next->index +1)+" "+to_string(index +1);if(mp.count(s)==0){ mp[s]++; ans++;}//if not already checked we can increase count in map}if(prev != s.end()&&doIntersect(arr[prev->index], arr[index])){
string s =to_string(prev->index +1)+" "+to_string(index +1);if(mp.count(s)==0){ mp[s]++; ans++;}//if not already checked we can increase count in map}// if same line segment is there then decrease answer as it got increased twiceif(prev != s.end()&& next != s.end()&& next->index == prev->index)ans--;// Insert current point (or event)
s.insert(curr);}// If current point is right of its segmentelse{// Find the iteratorauto it = s.find(Event(arr[index].left.x, arr[index].left.y,true, index));// Find above and below pointsauto next =succ(s, it);auto prev =pred(s, it);// If above and below point intersectif(next != s.end()&& prev != s.end()){
string s =to_string(next->index +1)+" "+to_string(prev->index +1);
string s1 =to_string(prev->index +1)+" "+to_string(next->index +1);if(mp.count(s)==0&& mp.count(s1)==0&&doIntersect(arr[prev->index], arr[next->index]))
ans++;
mp[s]++;}// Remove current segment
s.erase(it);}}//print pair of lines having intersection
ofstream outfile("test.txt", std::ios::app);for(auto& pr : mp){//cout << pr.first[0] <<" "<< pr.first[1] << "\n";//cout << pr.first << "\n";
outfile << pr.first[0]<<" "<<pr.first[2]<< std::endl;/* cout << pr.first[0]<< "\n";
cout << pr.first[2] << "\n";
cout << arr[pr.first[2]].left.x << "\n";*//*struct Point respoint = intersectionaxis(arr[pr.first[0]].left, arr[pr.first[0]].right, arr[pr.first[2]].left, arr[pr.first[2]].right);
cout << respoint.x << " " << respoint.y;*/}
outfile.close();return ans;}// Driver codeintmain(){//Segment arr[] = { {{1, 5}, {4, 5}}, {{2, 5}, {10, 1}},{{3, 2}, {10, 3}},{{6, 4}, {9, 4}},{{7, 1}, {8, 1}} };//Segment arr[] = { {{1, 0}, {1, 1}}, {{1,0}, {5,5}}};
Segment arr[2];
arr[0].left.x =1;
arr[0].left.y =0;
arr[0].right.x =5;
arr[0].right.y =5;
arr[1].left.x =1;
arr[1].left.y =1;
arr[1].right.x =3;
arr[1].right.y =0;/*arr[2].left.x = 0;
arr[2].left.y = 0;
arr[2].right.x = 3;
arr[2].right.y = 2;*//*cout << sizeof(arr)<<"\n";*/int n =sizeof(arr)/sizeof(arr[0]);//cout << n;isIntersect(arr, n);/*cout << isIntersect(arr, n);*//*读取保存那些线相交的txt文件,并将有哪些线相交记录下来,比如 第一行是3 2 表示第二条和第三条线段相交*/
ifstream f;
f.open("test.txt");
string str;
vector<vector<int>> num;while(getline(f, str)){
istringstream input(str);
vector<int> tmp;int a;while(input >> a)
tmp.push_back(a);
num.push_back(tmp);}//cout << num[1][1];/*END 读取保存那些线相交的txt文件*/for(int i =0; i < num.size();++i){//cout << num[i][1]<<"\n";/*比如 第一行是3 2 表示第二条和第三条线段相交,则arr[num[i][0]-1] 表示相交的第一条线段*/
Point p1 = arr[num[i][0]-1].left;
Point q1 = arr[num[i][0]-1].right;
Point p2 = arr[num[i][1]-1].left;
Point q2 = arr[num[i][1]-1].right;/*cout <<p1.x << " " << p1.y << "\n";
cout << q1.x << " " << q1.y << "\n";
cout << p2.x << " " << p2.y << "\n";
cout << q2.x << " " << q2.y << "\n";*///cout << typeid(arr[num[i][0]].left.x).name();structPoint respoint =intersectionaxis( p1, q1, p2, q2);
cout << respoint.x <<" "<< respoint.y<<"\n";}//cout << (arr[1].right.x);system("pause");return0;}/*#####################################################################################################################
#####################################################################################################################
#####################################################################################################################*/
方法二:
```cpp
#include<iostream>#include<cmath>#include<cassert>usingnamespace std;/** Calculate determinant of matrix:
[a b]
[c d]
*/structPoint{double x, y;};inlinedoubleDet(double a,double b,double c,double d){return a * d - b * c;}/// Calculate intersection of two lines.
Point LineLineIntersect(Point p1,// Line 1 start
Point q1,// Line 1 end
Point p2,// Line 2 start
Point q2,// Line 2 enddouble& ixOut,double& iyOut)// Output {
Point respoint;double x1 = p1.x;double y1= q1.y;double x2 = q1.x;double y2 = q1.y;double x3 = p2.x;double y3 = p2.y;double x4 = q2.x;double y4 = q2.y;double detL1 =Det(x1, y1, x2, y2);double detL2 =Det(x3, y3, x4, y4);double x1mx2 = x1 - x2;double x3mx4 = x3 - x4;double y1my2 = y1 - y2;double y3my4 = y3 - y4;double denom =Det(x1mx2, y1my2, x3mx4, y3my4);if(denom ==0.0)// Lines don't seem to cross{
ixOut = NAN;
iyOut = NAN;
respoint.x= ixOut;
respoint.y = iyOut;//return false;}double xnom =Det(detL1, x1mx2, detL2, x3mx4);double ynom =Det(detL1, y1my2, detL2, y3my4);
ixOut = xnom / denom;
iyOut = ynom / denom;if(!isfinite(ixOut)||!isfinite(iyOut)){// Probably a numerical issue//return false;
respoint.x = NAN;
respoint.y = NAN;}//return true; //All OK
respoint.x = ixOut;
respoint.y = iyOut;return respoint;}intmain(){// **Simple crossing diagonal lines**// Line 1
Point p1;
Point q1;
Point p2;
Point q2;double x1 =0.0, y1 =1.0;double x2 =5.0, y2 =1.0;// Line 2double x3 =1.0, y3 =0.0;double x4 =1.0, y4 =5.0;double ix =-1.0, iy =-1.0;
p1.x= x1;
q1.y= y1;
q1.x= x2;
q1.y=y2;
p2.x= x3 ;
p2.y= y3;
q2.x= x4;
q2.y= y4;
Point respoint =LineLineIntersect(p1,q1,p2,q2, ix, iy);
cout << respoint.x <<","<< respoint.y << endl;//double eps = 1e-6;/*assert(result == true);
assert(fabs(ix - 5.0) < eps);
assert(fabs(iy - 5.0) < eps);*/system("pause");return0;}