Last active
October 30, 2018 14:26
-
-
Save yadav26/dc228772927a91194087ef3280866678 to your computer and use it in GitHub Desktop.
Find overlap rectangles and probe colors of different points
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// FindGrpahColor.cpp | |
// | |
#include <iostream> | |
#include <memory> | |
#include <fstream> | |
#include <algorithm> | |
#include <functional> | |
#include <vector> | |
#include <string> | |
#include <map> | |
using namespace std; | |
//Split string at delimiter and form a collection - generic code | |
vector<string> split(string phrase, string delimiter) { | |
vector<string> list; | |
string s = phrase; | |
size_t pos = 0; | |
string token; | |
while ((pos = s.find(delimiter)) != string::npos) { | |
token = s.substr(0, pos); | |
list.push_back(token); | |
s.erase(0, pos + delimiter.length()); | |
} | |
list.push_back(s); | |
return list; | |
} | |
bool IsValidString(string &str) | |
{ | |
if (str.size() == 0) | |
{ | |
return false; | |
} | |
if (str.at(0) == '#') | |
{ | |
return false; | |
} | |
return true; | |
} | |
class chart { | |
//Topleft = X1,Y1 | |
//BottomRight = X2,Y2 | |
int _x1 = 0; | |
int _y1 = 0; | |
int _x2 = 0; | |
int _y2 = 0; | |
//Color RGB | |
int _red = 0; | |
int _green = 0; | |
int _blue = 0; | |
public: | |
chart() = delete; | |
chart(int x1, int y1, int x2, int y2, int r, int g, int b) : _x1(x1), _y1(y1), _x2(x2), _y2(y2), _red(r), _green(g), _blue(b) { } | |
~chart() { /*cout << "chart :: destructor called." << endl;*/ } | |
int getX1() { return _x1; } | |
int getX2() { return _x2; } | |
int getY1() { return _y1; } | |
int getY2() { return _y2; } | |
int getR() { return _red; } | |
int getG() { return _green; } | |
int getB() { return _blue; } | |
}; | |
typedef std::shared_ptr<chart> shChartPtr; | |
typedef std::vector< shChartPtr > vshChartCollection; | |
shChartPtr getChartshPtr(vector<string>& v1, vector<string>& v2) | |
{ | |
string::size_type sz; // alias of size_t | |
return shChartPtr( new chart(stoi(v1[0], &sz), | |
stoi(v1[1], &sz), | |
stoi(v1[2], &sz), | |
stoi(v1[3], &sz), | |
stoi(v2[0], &sz), | |
stoi(v2[1], &sz), | |
stoi(v2[2], &sz)) ); | |
} | |
class View { | |
int _id=0; // viewid | |
int _rp = 0; // probed redcolor store | |
int _gp = 0; // probed greencolor store | |
int _bp = 0; // probed bluecolor store | |
vshChartCollection _vshchartCol; | |
//validate input charts | |
bool IsInputChartValid(shChartPtr var) | |
{ | |
int x1 = var->getX1(); | |
int y1 = var->getY1(); | |
int x2 = var->getX2(); | |
int y2 = var->getY2(); | |
//no negative value | |
if (x1 < 0 || | |
x2 < 0 || | |
y1 < 0 || | |
y2 < 0 | |
) { | |
cout << endl << _id << " : Negative dimensions not allwoed."; | |
return false; | |
} | |
//chart should have correctly managed dimensions TopLeft(X1,Y1) | |
if ((x1 >= x2) || (y2 >= y1)) { | |
cout << endl << _id << " : Chart Dimensions are incorrect topLeftX < BottomRightX And TopLeftY > BottomRightY."; | |
return false; | |
} | |
//chart should have valid color range | |
if (var->getR() < 0 || var->getR() > 255 || | |
var->getG() < 0 || var->getG() > 255 || | |
var->getB() < 0 || var->getB() > 255 | |
) { | |
cout << endl << _id << " : Invalid Color codes must be in 0-255 range."; | |
return false; | |
} | |
return true; | |
} | |
//Validate all charts; remove all invalid charts from collection and return size | |
int ValidateAll_InputCharts() | |
{ | |
for (vshChartCollection::iterator it = _vshchartCol.begin(); it != _vshchartCol.end(); ) | |
{ | |
if (false == IsInputChartValid(*it)) | |
it = _vshchartCol.erase(it); | |
else | |
++it; | |
} | |
//_vshchartCol.remove_if(IsInputChartValid); | |
//vshChartCollection::iterator new_end = std::remove_if(_vshchartCol.begin(), _vshchartCol.end(), | |
//IsInputChartValid); | |
//_vshchartCol.erase(new_end, _vshchartCol.end()); | |
return _vshchartCol.size(); | |
} | |
public: | |
int getTCId() { return _id; } | |
int getRP() { return _rp; } | |
int getGP() { return _gp; } | |
int getBP() { return _bp; } | |
bool IsPresentInChart(chart* ch, int x, int y); | |
//Probe the color of the cordinate | |
void FindAverageColor(int probeX, int probeY); | |
View(int id, vshChartCollection vc) : _id(id), _vshchartCol(vc){ } | |
vshChartCollection& getChartshCol() { return _vshchartCol; } | |
~View() { /*cout << "View :: Destructor called." << endl;*/ } | |
int DoChartsOverlap(); | |
bool DoTwoChartsOverlap(shChartPtr var1, shChartPtr var2); | |
bool FindTwoChartOverlap_IF(shChartPtr aptr, shChartPtr bptr); | |
bool IsPresentInSharedChart(shChartPtr ch, int x, int y); | |
void SetAvgColorSharedPtr(int probeX, int probeY); | |
int FindAllTwoCombinationOverlaps(); | |
}; | |
typedef std::shared_ptr<View> ViewPtr; | |
typedef std::vector<ViewPtr> ViewCollection; | |
ViewCollection viewshCollection; | |
typedef std::map<vshChartCollection, int > MapStore; | |
typedef MapStore::iterator itMapStore; | |
int View::FindAllTwoCombinationOverlaps() | |
{ | |
int overlapCnt = 0, nonOverlapCnt = 0, repeated = 0; | |
int testCounter = 0; | |
vshChartCollection vtemp, vtemp2; | |
vshChartCollection::iterator vit; | |
MapStore mpStore; | |
itMapStore it; | |
for (auto& var1 : _vshchartCol) { | |
vtemp.clear(); | |
for (auto& var2 : _vshchartCol) { | |
vtemp.clear(); | |
if (var1 == var2) | |
continue; | |
for (it = mpStore.begin(); it != mpStore.end(); ++it) | |
{ | |
vtemp2 = it->first; | |
int val = it->second; | |
if ((vtemp2[0] == var1 && vtemp2[1] == var2) || | |
(vtemp2[0] == var2 && vtemp2[1] == var1) | |
) | |
{ | |
//cout << "already tested A-B or B-A ignoring."<<endl; | |
repeated++; | |
} | |
} | |
if (FindTwoChartOverlap_IF(var1, var2) == true) | |
{ | |
//cout << endl << endl << "ViewID - " << _id << ":OVERLAP DETECTED " << endl; | |
//cout << "TopLeft____(x1,y1) = " << var1->getX1() << ", " << var1->getY1() << endl; | |
//cout << "BottomRight(x2,y2) = " << var1->getX2() << ", " << var1->getY2() << endl; | |
//cout << "TopLeft____(p1,q1) = " << var2->getX1() << ", " << var2->getX2() << endl; | |
//cout << "BottomRight(p2,q2) = " << var2->getX2() << ", " << var2->getY2() << endl; | |
++overlapCnt; | |
} | |
else | |
{ | |
++nonOverlapCnt; | |
} | |
vtemp.push_back(var1); | |
vtemp.push_back(var2); | |
mpStore.insert(std::pair< vshChartCollection, int >(vtemp, testCounter++)); | |
} | |
} | |
//cout << "\nOverlap = " << overlapCnt << endl; | |
//cout << "Non Overlap = " << nonOverlapCnt<< endl; | |
return overlapCnt; | |
} | |
//Figure out if chart overlaps, | |
int View::DoChartsOverlap( ) | |
{ | |
if ( ValidateAll_InputCharts() < 2 ) | |
return 0; | |
return FindAllTwoCombinationOverlaps(); | |
} | |
//Figure out if chart overlaps | |
bool View::DoTwoChartsOverlap(shChartPtr var1, shChartPtr var2) | |
{ | |
if (false == (IsInputChartValid(var1) && IsInputChartValid(var2))) | |
return false; | |
if (true == FindTwoChartOverlap_IF(var1, var2)) | |
return true; | |
else | |
return false; | |
} | |
bool View::IsPresentInSharedChart(shChartPtr ch, int x, int y) | |
{ | |
int x1 = ch->getX1(); | |
int y1 = ch->getY1(); | |
int x2 = ch->getX2(); | |
int y2 = ch->getY2(); | |
if ((x > x1 && x2 > x) && (y1 > y && y > y2)) | |
return true; | |
return false; | |
} | |
void View::SetAvgColorSharedPtr(int probeX, int probeY) | |
{ | |
int i = 0; | |
int r = 0, g = 0, b = 0; | |
for (auto& var : getChartshCol()) { | |
if (true == IsPresentInSharedChart(var, probeX, probeY)) | |
{ | |
#if __DBG | |
cout << "Probe belong to chart - " << i << endl; | |
#endif | |
r += var->getR(); | |
g += var->getG(); | |
b += var->getB(); | |
++i; | |
} | |
} | |
if (i == 0) | |
return; | |
_rp = r / i; | |
_gp = g / i; | |
_bp = b / i; | |
} | |
/* | |
Biggest function to find if the charts overlaps. Check 4 overlap criteria | |
1. Corners overlap | |
2. Edge Overlap | |
3. Nested graph | |
4. Partial containment | |
*/ | |
bool View::FindTwoChartOverlap_IF(shChartPtr var1, shChartPtr var2) { | |
//auto var = getChartshCol(); | |
//auto var1 = var[0]; | |
//auto var2 = var[1]; | |
int x1 = var1->getX1(); | |
int y1 = var1->getY1(); | |
int x2 = var1->getX2(); | |
int y2 = var1->getY2(); | |
int p1 = var2->getX1(); | |
int q1 = var2->getY1(); | |
int p2 = var2->getX2(); | |
int q2 = var2->getY2(); | |
int tcid = _id; | |
if ((x1<p1) && (p1<x2) && (x2<p2)) //x1<p1<x2<p2 // RIGHT EDGE CHARTS MOVE | |
{ | |
if ((y1>q1) && (q1>y2) && (y2>q2)) | |
{//bottom right corner | |
//cout << endl << _id << " - Bottom-Right Corner"; | |
return true; | |
} | |
if ((y1 >= q1) && (q2 >= y2)) | |
{ | |
//cout << endl << _id << " - RIGHT In-Edge"; | |
return true; | |
} | |
if ((q1 >= y1) && (y2 >= q2)) | |
{ | |
//cout << endl << _id << " - Right OUT-EDGE "; | |
return true; | |
} | |
if ((q1>y1) && (y1>q2) && (q2>y2)) | |
{ | |
//cout << endl << _id << " - TOP Right Corner"; | |
return true; | |
} | |
} | |
if ((p1<x1) && (x1<p2) && (p2<x2)) // left p1<x1<p2<x2 | |
{ | |
if ((y1>q1) && (q1>y2) && (y2>q2)) // y1>q1>y1>q2 | |
{ | |
//cout << endl << _id << " - LEFT - BottomCorner"; | |
return true; | |
} | |
if ((y1 >= q1) && (q2 >= y2)) // y1>q1>q2>y2 | |
{ | |
//cout << endl << _id << " - LEFT - InEdge "; | |
return true; | |
} | |
if ((q1 >= y1) && (y2 >= q2)) // q1>y1>y2>q2 | |
{ | |
//cout << endl << _id << " - LEFT - OutEdge "; | |
return true; | |
} | |
if ((q1>y1) && (y1>q2) && (q2>y2)) // q1>y1>y2>q2 | |
{ | |
//cout << endl << _id << " - LEFT - TOP Corner"; | |
return true; | |
} | |
} | |
if ((q1>y1) && (y1>q2) && (q2>y2)) // q1>y1>q2>y2 //top right corner | |
{ | |
if ((p1<x1) && (x1<p2) && (p2<x2)) // p1>x1>p2>x2 | |
{ | |
//cout << endl << _id << " - TOP ->Left Corner"; | |
return true; | |
} | |
if ((x1 <= p1) && (p2 <= x2)) // x1<p1<p2<x2 | |
{ | |
//cout << endl << _id << " - TOP InnerEdge"; | |
return true; | |
} | |
if ((p1 <= x1) && (x2 <= p2)) // p1<x1<x2<p2 | |
{ | |
//cout << endl << _id << " - TOP Out-Edge"; | |
return true; | |
} | |
if ((x1<p1) && (p1<x2) && (x2<p2)) // x1<p1<x2<p2 | |
{ | |
//cout << endl << _id << " - TOP ->Right Corner"; | |
return true; | |
} | |
} | |
if ((y1>q1) && (q1>y2) && (y2>q2))//y1>q1>y2>q2 bottom | |
{ | |
if (q2 > x1) | |
{ | |
//cout << endl << _id << " - No OverLap"; | |
return true; | |
} | |
if ((p1<x1) && (x1<p2) && (p2<x2)) { | |
//cout << endl << _id << " - Bottom Left Corner."; | |
return true; | |
} | |
if ((x1 <= p1) && (p2 <= x2)) { | |
//cout << endl << _id << " - Bottom INEDGE"; | |
return true; | |
} | |
if ((p1 <= x1) && (x2 <= p2)) { | |
//cout << endl << _id << " - Bottom OUT-EDGE"; | |
return true; | |
} | |
if ((x1<p1) && (p1<x2) && (x2<p2)) { | |
//cout << endl << _id << " - Bottom Right Corner"; | |
return true; | |
} | |
} | |
if ((q1 >= y1) && (y2 >= q2) && (x1 <= p1) && (p2 <= x2)) { | |
//cout << endl << _id << " - Vertical Intrunk overlap."; | |
return true; | |
} | |
if ((y1 >= q1) && (q2 >= y2) && (p1 <= x1) && (x2 <= p2)) { | |
//cout << endl << _id << " - Horizontal Intrunk overlap."; | |
return true; | |
} | |
if (((p1 <= x1) && (p2 >= x2) && (q1 >= y1) && (y2 >= q2)) || | |
((x1 <= p1) && (p2 <= x2) && (y1 >= q1) && (q2 >= y2)) | |
) // nesting ?? | |
{ | |
//cout << endl << _id << " - Nested boxes ."; | |
return true; | |
} | |
// Following code to find out the failing / non overlapping maps | |
#if __DBG | |
cout << endl << endl << "ViewID - " << _id << ": NO OVERLAP DETECTED " << endl; | |
cout << "TopLeft____(x1,y1) = " << x1 << ", " << y1 << endl; | |
cout << "BottomRight(x2,y2) = " << x2 << ", " << y2 << endl; | |
cout << "TopLeft____(p1,q1) = " << p1 << ", " << q1 << endl; | |
cout << "BottomRight(p2,q2) = " << p2 << ", " << q2 << endl; | |
#endif | |
return false; | |
} | |
bool readInputs(string path) | |
{ | |
std::ifstream file(path); | |
if (!file) | |
return false; | |
if (file.is_open()) | |
{ | |
std::string line; | |
int testCaseId = 0; | |
while (getline(file, line)) | |
{ | |
//cout << line << endl; | |
if (false == IsValidString(line)) | |
continue; | |
string::size_type sz; // alias of size_t | |
int nCharts = std::stoi(line, &sz); | |
std::string tmp; | |
vector<string> listCordinates; | |
vector<string> listColors; | |
//vChartCollection vc; | |
vshChartCollection vshc; | |
for (int count = 0; count < nCharts; ++count) | |
{ | |
listCordinates.clear(); | |
listColors.clear(); | |
getline(file, tmp); | |
//cout << tmp << endl; | |
if (false == IsValidString(line)) | |
continue; | |
listCordinates = split(tmp, ","); | |
getline(file, tmp); | |
//cout << tmp << endl; | |
if (false == IsValidString(line)) | |
continue; | |
listColors = split(tmp, ","); | |
shChartPtr pshTemp = getChartshPtr(listCordinates, listColors); | |
vshc.push_back(pshTemp); | |
} | |
ViewPtr val = ViewPtr(new View(testCaseId++, vshc)); | |
viewshCollection.push_back(val); | |
} | |
} | |
file.close(); | |
return true; | |
} | |
/* | |
Inputs are read from an input file. Original Input formatted file is supplied under name "Input_org.txt" | |
Number of chart in this view | |
Topleft cordinate of chart 1, Bottom-RightCordinate of chart-1( X1,Y1,X2,Y2 ) | |
RGB of chart 1 | |
Topleft cordinate of chart 2,, Bottom-RightCordinate of chart-2( P1,Q1,P2,Q2 ) | |
RGB of chart 2 | |
# = comment ignored | |
1. Get total "combination of 2" overlapping charts | |
For single View, enter only one View entry | |
2. Probe points/cordinates are hardcoded value | |
Limitation - | |
no proper format shared for how many color probes per View, hence it has to be tested manually | |
everytime, how to do - example is present state | |
1. enter only single View details in input file. | |
2. Modify source for Probe Cordinates | |
Output - | |
ViewID-0 - R= 0, G= 0, B= 0 | |
ViewID-0 - R= 10, G= 20, B= 30 | |
ViewID-0 - R= 40, G= 50, B= 60 | |
ViewID-0 - R= 25, G= 35, B= 45 | |
*/ | |
int main( int argc, char**argv ) | |
{ | |
string path = argv[1] ? argv[1]: ""; | |
if (false == readInputs(path)) | |
{ | |
cout << "Input test cases file read failed. path issue." << endl; | |
return 0; | |
} | |
int counter = 0; | |
for( auto& var : viewshCollection) | |
{ | |
cout << "\n\nViewID-" << var->getTCId() << ": Total Charts in View - " << var->getChartshCol().size() ; | |
counter = var->DoChartsOverlap(); | |
cout << "\nChart Overlapped - " << counter ; | |
/* | |
Hardcoded static color probing points, Call SetAvgColorSharedPtr for each point to be probed. | |
*/ | |
//Probe A - outside of both charts | |
var->SetAvgColorSharedPtr(10, 10); | |
cout << "\nProbePointColor => R= " <<var->getRP() << ", G= "<< var->getGP()<< ", B= "<< var->getBP() ; | |
////Probe B - Inside Chart A => should return Chart A colors | |
//var->SetAvgColorSharedPtr(15, 35); | |
//cout << "ViewID-" << var->getTCId() << " - R= " << var->getRP() << ", G= " << var->getGP() << ", B= " << var->getBP() << endl; | |
////Probe C - Inside Chart B => should return Chart B colors | |
//var->SetAvgColorSharedPtr(25, 15); | |
//cout << "ViewID-" << var->getTCId() << " - R= " << var->getRP() << ", G= " << var->getGP() << ", B= " << var->getBP() << endl; | |
////Probe D - Inside Overlap => should return average | |
//var->SetAvgColorSharedPtr(25, 25); | |
//cout << "ViewID-" << var->getTCId() << " - R= " << var->getRP() << ", G= " << var->getGP() << ", B= " << var->getBP() << endl; | |
} | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Question Statement - Give two rectangles (TopLeft) and (BottomRight) cordinates and their color respectively, Find
1 . if they overlap
2. Color of a coordinate , if lies in overlapping zone get the average of two colors.