#pragma once #include "pch.h" #include "ArrangementFunctions.h" #include "ArtGallery.h" #include "Convex_expansion_visibility_2_temp.h" #include "IOHandling.h" #include "IPSolver.h" #include "MikkelVisibility.h" #include "PointFunctions.h" #include "Visibility.h" #include "WeakVisDecomp.h" typedef Convex_expansion_visibility_2 CEV; class ArtGalleryImpl { public: ArtGallery* wrapper; IPSolver IP; //vector vertexHandles; //Save reflex details, used for splits etc... vector> reflexNeighbours = {}; vector reflexHandles = {}; vector> chords = {}; //chords between reflex vertices that can see eachother! //Visibility unique_ptr vis; shared_ptr weakVisRoot; int maxGranularity = pow(2, 6); //default value? ArtGalleryImpl(ArtGallery* wrapper) { vis = unique_ptr(new Visibility()); this->wrapper = wrapper; //Make sure thePolygon is filled IOHandling::GetTestPolygon(wrapper->testPolygonID, wrapper->currentSize, wrapper->inTestMode, vis->polygonBoundary); IOHandling::SetDimensions(vis->polygonBoundary); vis->attach(&IP, wrapper->criticalThreshold); IOHandling::GetTestPolygon(wrapper->testPolygonID, wrapper->currentSize, wrapper->inTestMode, vis->thePolygon); //Identify reflex vertices //use do/while for circular loop //The polygon is a "hole" in the unbounded face of the arrangement, thus a clockwise inner_ccb auto eit = *vis->thePolygon.unbounded_face()->inner_ccbs_begin(); do { //Assign ids to vertices (this is their polygonal ID, used for the shortest path map later! eit->source()->data().isOriginal = true; //Left turn, because the boundary is clockwise... if (CGAL::orientation(eit->prev()->source()->point(), eit->prev()->target()->point(), eit->target()->point()) == CGAL::LEFT_TURN) { //eit->source() is a reflex vertex... eit->source()->data().isReflex = true; reflexHandles.push_back(eit->source()); reflexNeighbours.push_back( make_pair(eit->prev()->source(), eit->target() )); } } while (++eit != *(vis->thePolygon.unbounded_face()->inner_ccbs_begin())); } bool initialize() { auto timeBegin = IOHandling::get_cpu_time(); Arrangement_2 theRotatedPolygon = rotateArrangement(vis->thePolygon); //Shoot orthogonal rays for (size_t i = 0; i < reflexHandles.size(); i++) { Point_2 prevPoint = reflexNeighbours[i].first->point(); Point_2 reflexPoint = reflexHandles[i]->point(); Point_2 nextPoint = reflexNeighbours[i].second->point(); bool goUp, goDown, goRight, goLeft; goUp = goDown = goRight = goLeft = true; auto vit = reflexHandles[i]->incident_halfedges(); do { //check for verticalities, because CGAL's shoot_up/shoot_down bugs out otherwise... //target is our reflex vertex... if (vit->curve().is_vertical()) { if (vit->source()->point().y() > reflexPoint.y()) goUp = false; else goDown = false; } else if (vit->source()->point().y() == vit->target()->point().y()) { if (vit->source()->point().x() > reflexPoint.x()) goRight = false; else goLeft = false; } } while (++vit != reflexHandles[i]->incident_halfedges()); vector newVertices = shootRayUpDown(vis->thePolygon, reflexPoint, goUp, goDown); vector rVertices = shootRayUpDown(theRotatedPolygon, rotatePointRight(reflexPoint), goLeft, goRight); for (auto &rVertex : rVertices) newVertices.push_back(rotatePointLeft(rVertex)); for (auto newVertex : newVertices) { //check if the point is contained inside the polygon... //(if it is to the right of one of the two incident reflex segments its okay (right because we found these edges going clockwise)) if (CGAL::orientation(prevPoint, reflexPoint, newVertex) == CGAL::RIGHT_TURN || CGAL::orientation(reflexPoint, nextPoint, newVertex) == CGAL::RIGHT_TURN) { Arrangement_2::X_monotone_curve_2 toInsert(reflexPoint, newVertex); /*if (toInsert.is_directed_right()) { vis->thePolygon.insert_at_left }*/ //TODO: improve insert? CGAL::insert(vis->thePolygon, Segment_2(reflexPoint, newVertex)); //the reflex vertex is the starting point //insert into both arrangements CGAL::insert(theRotatedPolygon, Segment_2(rotatePointRight(reflexPoint), rotatePointRight(newVertex))); } } } auto timeEnd = IOHandling::get_cpu_time(); chrono::duration time_span = chrono::duration_cast>(timeEnd - timeBegin); wrapper->preprocessingTime += time_span.count(); timeBegin = IOHandling::get_cpu_time(); //compute all visibilities that we still have to for (auto vit = vis->thePolygon.vertices_begin(); vit != vis->thePolygon.vertices_end(); ++vit) if(!vit->data().created) vis->prepareGuard(vit, FaceGuard()); for (auto vit = vis->thePolygon.vertices_begin(); vit != vis->thePolygon.vertices_end(); ++vit) { if (!vit->data().created) { vit->data().created = true; vis->updateVisibilities(vit); } } for (auto fit = vis->thePolygon.faces_begin(); fit != vis->thePolygon.faces_end(); ++fit) if (fit->has_outer_ccb() && !fit->data().created) vis->prepareGuard(fit, FaceGuard()); for (auto fit = vis->thePolygon.faces_begin(); fit != vis->thePolygon.faces_end(); ++fit) { if (fit->has_outer_ccb() && !fit->data().created) { fit->data().created = true; vis->updateVisibilities(fit); } } timeEnd = IOHandling::get_cpu_time(); time_span = chrono::duration_cast>(timeEnd - timeBegin); wrapper->processingTime += time_span.count(); //Compute chords for splits! for (auto vit = reflexHandles.begin(); vit != reflexHandles.end(); ++vit) { //for every other reflex vertex for (auto vit2 = vit + 1; vit2 != reflexHandles.end(); ++vit2) { //if they see eachother: save reflex chord if (vis->seesWitness(*vit, *vit2)) chords.push_back(make_pair(*vit, *vit2)); } } string fileString; if(wrapper->inTestMode) fileString = to_string(wrapper->currentSize) + "-" + to_string(wrapper->testPolygonID) + "/" + wrapper->initSVGString; else fileString = testPolygonNames[wrapper->testPolygonID] + "/" + wrapper->initSVGString; //returns true if not in Drawmode. Otherwise draws polygon and returns result return !wrapper->inDrawMode || IOHandling::DrawArtGallery(vis->thePolygon, fileString, IP); } bool preProcess() { auto timeBegin = IOHandling::get_cpu_time(); //Set-up weak visibility decomp O(n^2)?) auto eit = *vis->thePolygon.unbounded_face()->inner_ccbs_begin(); //random edge WeakVisNode::weakVisCounter = 0; weakVisRoot = shared_ptr(new WeakVisNode(vis->thePolygon, vis->thePolygon, 0, eit->twin(), wrapper->useWeakVis)); //build the weak visibility vector for constant look-up vis->weakVisNodes.push_back(weakVisRoot); vector> rootSubTree = weakVisRoot->subTree(); vis->weakVisNodes.insert(vis->weakVisNodes.end(), rootSubTree.begin(), rootSubTree.end()); auto timeEnd = IOHandling::get_cpu_time(); chrono::duration time_span = chrono::duration_cast>(timeEnd - timeBegin); wrapper->preprocessingTime += time_span.count(); string fileString; if (wrapper->inTestMode) fileString = to_string(wrapper->currentSize) + "-" + to_string(wrapper->testPolygonID) + "/" + wrapper->decompSVGString; else fileString = testPolygonNames[wrapper->testPolygonID] + "/" + wrapper->decompSVGString; //returns true if not inDrawMode. Otherwise draws polygon and returns result return !wrapper->inDrawMode || IOHandling::DrawDecomposition(vis->thePolygon, weakVisRoot, fileString); } bool angularSplit(Face_handle& toSplit, int raysStart, bool preferIncident) { //choose reflex vertices in random order vector indices(reflexHandles.size()); iota(begin(indices), end(indices), 0); random_shuffle(indices.begin(), indices.end()); bool incidentFound = false; for (auto it = indices.begin(); it != indices.end() - 1 && !incidentFound; it++) { if (vis->seesWitness(toSplit, reflexHandles[*it])) { auto eit = toSplit->outer_ccb(); do { if (eit->source()->data().id == reflexHandles[*it]->data().id) { //we are the indicent vertex! iter_swap(it, indices.end() - 1); incidentFound = true; } } while (++eit != toSplit->outer_ccb() && !incidentFound); } } if(incidentFound && !preferIncident && indices.size() > 1) indices.pop_back(); int maximumGranularity = maxGranularity; int numberOfRays = raysStart; while (numberOfRays <= maximumGranularity) { bool seenByAReflex = false; for (auto it = indices.begin(); it != indices.end(); it++) { if (vis->seesWitness(toSplit, reflexHandles[*it])) { seenByAReflex = true; //using the current granularity, try to find a reflex vertex that has at least two intersections! Segment_2 firstIntersection; int firstIntersectionID = 0; //First shoot up bool foundIntersection = properIntersectFace(toSplit, getRay(numberOfRays, 0, reflexHandles[*it]->point()), firstIntersection); int low = 0; int high = numberOfRays - 1; int mid; //binary search for intersection while (!foundIntersection && low <= high) { mid = (low + high) / 2; Ray_2 midRay = getRay(numberOfRays, mid, reflexHandles[*it]->point()); foundIntersection = properIntersectFace(toSplit, midRay, firstIntersection); if (foundIntersection) { firstIntersectionID = mid; break; //done } //Check if we are right or left auto eit = toSplit->outer_ccb(); CGAL::Orientation orCheck; do { orCheck = midRay.supporting_line().oriented_side(eit->source()->point()); eit++; } while (orCheck == CGAL::COLLINEAR); //if we are collinear check another point :( //Are we left of the line? if (orCheck == CGAL::LEFT_TURN) high = mid - 1; else low = mid + 1; } if (foundIntersection) { vector intersections; vector intersectionRayIDs; //look left of firstIntersectionID int rayID = (firstIntersectionID + (numberOfRays - 1)) % numberOfRays; //decrement one "on the clock" Segment_2 nextIntersection; Ray_2 nextRay = getRay(numberOfRays, rayID, reflexHandles[*it]->point()); bool weIntersect = properIntersectFace(toSplit, nextRay, nextIntersection); while (weIntersect){ intersections.push_back(nextIntersection); intersectionRayIDs.push_back(rayID); rayID = (rayID + (numberOfRays - 1)) % numberOfRays; //decrement one "on the clock" nextRay = getRay(numberOfRays, rayID, reflexHandles[*it]->point()); weIntersect = properIntersectFace(toSplit, nextRay, nextIntersection); } reverse(intersections.begin(), intersections.end()); //reverse the ones we found so far, they are in the wrong order reverse(intersectionRayIDs.begin(), intersectionRayIDs.end()); intersections.push_back(firstIntersection); //add the first one intersectionRayIDs.push_back(firstIntersectionID); //look right of firstIntersectionID rayID = (firstIntersectionID + 1) % numberOfRays; //increment one "on the clock" nextRay = getRay(numberOfRays, rayID, reflexHandles[*it]->point()); weIntersect = properIntersectFace(toSplit, nextRay, nextIntersection); while (weIntersect) { intersectionRayIDs.push_back(rayID); intersections.push_back(nextIntersection); rayID = (rayID + 1) % numberOfRays; nextRay = getRay(numberOfRays, rayID, reflexHandles[*it]->point()); weIntersect = properIntersectFace(toSplit, nextRay, nextIntersection); } if (intersections.size() > 1) { int middle = intersections.size() / 2; //integer division rounds down Segment_2 middleSegment; bool foundIt = true; //If we are odd we take the middle one (most central) //If we are even, we shoot the middle ray in the next level of granularity, so we double number of rays if (intersections.size() % 2 > 0) middleSegment = intersections[middle]; else foundIt = properIntersectFace(toSplit, getRay(numberOfRays * 2, intersectionRayIDs[middle] * 2 - 1, reflexHandles[*it]->point()), middleSegment); if (numberOfRays > wrapper->currentGranularity) wrapper->currentGranularity = numberOfRays; wrapper->angularSplits++; vector sources = {}; vector targets = {}; for (auto &intersection : intersections) { sources.push_back(splitFaceEdge(vis->thePolygon, intersection.source(), toSplit)); targets.push_back(splitFaceEdge(vis->thePolygon, intersection.target(), toSplit)); } for (size_t i = 0; i < sources.size(); i++) { vis->thePolygon.insert_at_vertices(intersections[i], sources[i], targets[i]); } return true; } } } } if (!seenByAReflex) cout << "Why????whywhyhw"; numberOfRays = numberOfRays * 2; } return false; } void squareSplit(Face_handle& toSplit) { Arrangement_2 onlyFace; vector facePts; //Take necessary info auto eit = toSplit->outer_ccb(); do { facePts.push_back(eit->source()->point()); CGAL::insert(onlyFace, eit->curve()); } while (++eit != toSplit->outer_ccb()); Arrangement_2 rotatedFace = rotateArrangement(onlyFace); //Find middle of face and insert as vertex auto bbox = CGAL::bounding_box(facePts.begin(), facePts.end()); //otherwise we use center of bounding box Point_2 middle = Point_2(bbox.xmin() + (bbox.xmax() - bbox.xmin())/2, bbox.ymin() + (bbox.ymax() - bbox.ymin())/2); Vertex_handle midvertex = splitFaceEdge(vis->thePolygon, middle, toSplit); vector newPoints; vector horPoints = shootRayUpDown(rotatedFace, rotatePointRight(middle)); //Rotate them back for (auto horPoint : horPoints) newPoints.push_back(rotatePointLeft(horPoint)); vector verPoints = shootRayUpDown(onlyFace, middle); newPoints.insert(newPoints.end(), verPoints.begin(), verPoints.end()); vector newVertices; for (auto& pit : newPoints) { if (middle == pit) continue; else newVertices.push_back(splitFaceEdge(vis->thePolygon, pit, toSplit)); } for (auto& vit : newVertices) vis->thePolygon.insert_at_vertices(Segment_2(middle, vit->point()), midvertex, vit); wrapper->squareSplits++; } bool extensionSplit(Face_handle& toSplit) { //we will choose randomly! vector indices(reflexHandles.size()); iota(begin(indices), end(indices), 0); random_shuffle(indices.begin(), indices.end()); for (auto it = indices.begin(); it != indices.end(); it++) { if (vis->seesWitness(toSplit, reflexHandles[*it])) { //try to split using both reflex extensions if necessary Segment_2 intersections; //Because of the OR we only check the second one if we actually need to! if (properIntersectFace(toSplit, Ray_2(reflexNeighbours[*it].first->point(), reflexHandles[*it]->point()), intersections)) { //we have found some intersections we can use vis->thePolygon.insert_at_vertices( intersections, splitFaceEdge(vis->thePolygon, intersections.source(), toSplit), splitFaceEdge(vis->thePolygon, intersections.target(), toSplit) ); wrapper->extensionSplits++; return true; } else if (properIntersectFace(toSplit, Ray_2(reflexNeighbours[*it].second->point(), reflexHandles[*it]->point()), intersections)) { vis->thePolygon.insert_at_vertices( intersections, splitFaceEdge(vis->thePolygon, intersections.source(), toSplit), splitFaceEdge(vis->thePolygon, intersections.target(), toSplit) ); wrapper->extensionSplits++; return true; } } } return false; } bool chordSplit(Face_handle& toSplit) { //choose chords in random order vector indices(chords.size()); iota(begin(indices), end(indices), 0); random_shuffle(indices.begin(), indices.end()); for (auto it = indices.begin(); it != indices.end(); it++) { if (vis->seesWitness(toSplit, chords[*it].first) && vis->seesWitness(toSplit, chords[*it].second)) { //try to split using chord Segment_2 intersections; if (properIntersectFace(toSplit, Ray_2(chords[*it].first->point(), chords[*it].second->point()), intersections)) { //we have found some intersections we can use vis->thePolygon.insert_at_vertices( intersections, splitFaceEdge(vis->thePolygon, intersections.source(), toSplit), splitFaceEdge(vis->thePolygon, intersections.target(), toSplit) ); wrapper->chordSplits++; return true; } } } return false; } bool vislineSplit(Face_handle& toSplit, bool isGuard) { vector candidates; //identify split options if (isGuard) { for (auto& sv : toSplit->data().seenVertices) { if (!vis->seesWitness(vis->allVertices[sv.first], toSplit)) { bool onlyUs = true; //we see him but he does not see us (good news) //are we the only one that sees him? for (auto& vs : IP.vertexSolution) { if (vis->seesWitness(vs, vis->allVertices[sv.first])) { onlyUs = false; break; } } if (onlyUs) { for (auto& fs : IP.faceSolution) { if (fs->data().id != toSplit->data().id && vis->seesWitness(fs, vis->allVertices[sv.first])) { onlyUs = false; break; } } } if (onlyUs) //okay we satisfy all conditions candidates.push_back(vis->allVertices[sv.first]); } } } else{ //we want vertex guards that we can see (only those are interesting) for (auto& vs : IP.vertexSolution) { if (vis->seesWitness(toSplit, vs)) { vector seenFVertices = {}; auto eit = toSplit->outer_ccb(); do { if (vis->seesWitness(vs, eit->source())) seenFVertices.push_back(eit->source()); } while (++eit != toSplit->outer_ccb()); if (seenFVertices.size() > 2 || (seenFVertices.size() == 2 && !Line_2(vs->point(), seenFVertices[0]->point()).has_on(seenFVertices[1]->point()))) candidates.push_back(vs); } } } if (candidates.size() > 0) { //lets go //int rI = rand() % candidates.size(); random_shuffle(candidates.begin(), candidates.end()); vector> newVertices; for (auto &candidate : candidates) { for (auto pedge = vis->pointvisPolygons[candidate->data().id].edges_begin(); pedge != vis->pointvisPolygons[candidate->data().id].edges_end(); pedge++) { Segment_2 inter; if(properIntersectFace(toSplit, *pedge, inter)) newVertices.push_back(make_pair(splitFaceEdge(vis->thePolygon, inter.source(), toSplit), splitFaceEdge(vis->thePolygon, inter.target(), toSplit))); } if (!newVertices.empty()) break; } if (newVertices.empty()) return false; for (auto& newV : newVertices) vis->thePolygon.insert_at_vertices(Segment_2(newV.first->point(), newV.second->point()), newV.first, newV.second); wrapper->vislineSplits++; return true; } return false; } bool iterations() { auto timeBegin = IOHandling::get_cpu_time(); auto timePrev = timeBegin; wrapper->intermediateSteps = 0; do { //split faces if any for (auto fit = IP.bothFaces.begin(); fit != IP.bothFaces.end(); ++fit) { FaceGuard papa = (*fit)->data(); bool isGuard = find(IP.unseenFaces.begin(), IP.unseenFaces.end(), *fit) == IP.unseenFaces.end(); if ((*fit)->data().constraintAdded) IP.model.remove(IP.faceConstraints[papa.id]); //force it not to see anything IloExpr expr(IP.env); expr += IP.faceguardVar[papa.id] + IP.facewitnessVar[papa.id]; IloConstraint c(expr == 0); IP.model.add(c); int reflexCount = 0; //Check some things for split types... auto eit = (*fit)->outer_ccb(); do { if (eit->source()->data().isReflex) reflexCount++; } while (++eit != (*fit)->outer_ccb()); if (reflexCount > 1 || wrapper->doingP5) //P5 = only squaresplitz { //Do square split squareSplit(*fit); } else { int dice = rand() % 10 + 1; bool splitDone = false; if (dice <= 2) { //20% chance of extension split splitDone = extensionSplit(*fit); } else if (dice <= 4) { //10% chance of chord split splitDone = chordSplit(*fit); } else if (dice <= 6) { //50% of visline split splitDone = vislineSplit(*fit, isGuard); } if (!splitDone) { //otherwise do angular split! int raysStart = 16; splitDone = angularSplit(*fit, raysStart, false); //splitDone = true; //squareSplit(*fit); //try chord and extension first before increasing gran gran if (!splitDone) splitDone = extensionSplit(*fit); if (!splitDone) splitDone = chordSplit(*fit); while (!splitDone) { //here we either mark as unsplittable and use bigIP to continue raysStart = maxGranularity; //or change maxGran here maxGranularity = maxGranularity * 16; splitDone = angularSplit(*fit, raysStart, false); } } } //(*fit) is now a new face (*fit)->set_data(FaceGuard()); //now we are done splitting... for (auto nvit = vis->thePolygon.vertices_begin(); nvit != vis->thePolygon.vertices_end(); nvit++) if (!nvit->data().created) vis->prepareGuard(nvit, papa); for (auto nvit = vis->thePolygon.vertices_begin(); nvit != vis->thePolygon.vertices_end(); nvit++) { if (!nvit->data().created) { nvit->data().created = true; vis->updateVisibilities(nvit); } } //handle all new faces and vertices for (auto nfit = vis->thePolygon.faces_begin(); nfit != vis->thePolygon.faces_end(); nfit++) if (!nfit->data().created && nfit->has_outer_ccb()) vis->prepareGuard(nfit, papa); int nfaces = 0; for (auto nfit = vis->thePolygon.faces_begin(); nfit != vis->thePolygon.faces_end(); nfit++) { if (!nfit->data().created && nfit->has_outer_ccb()) { nfaces++; nfit->data().created = true; vis->updateVisibilities(nfit); } } } //Critical loop! bool allAreSeen = true; bool preferGuards = (wrapper->intermediateSteps % 2) == 0; do { //Find next solution IP.findSolution(vis->thePolygon, preferGuards, wrapper->doingP5); if (wrapper->criticalThreshold < 100) allAreSeen = vis->verifySolution(); } while (!allAreSeen); string fileString; string fileStringCrit; string fileStringFace; if (wrapper->inDrawMode) { if (wrapper->inTestMode) { fileString = to_string(wrapper->currentSize) + "-" + to_string(wrapper->testPolygonID) + "/" + wrapper->intermediateSVGString + to_string(wrapper->intermediateSteps); fileStringCrit = to_string(wrapper->currentSize) + "-" + to_string(wrapper->testPolygonID) + "/" + wrapper->criticalSVGString + to_string(wrapper->intermediateSteps); fileStringFace = to_string(wrapper->currentSize) + "-" + to_string(wrapper->testPolygonID) + "/face_visibility - " + to_string(wrapper->intermediateSteps) + "-"; } else { fileString = testPolygonNames[wrapper->testPolygonID] + "/" + wrapper->intermediateSVGString + to_string(wrapper->intermediateSteps); fileStringCrit = testPolygonNames[wrapper->testPolygonID] + "/" + wrapper->criticalSVGString + to_string(wrapper->intermediateSteps); fileStringFace = testPolygonNames[wrapper->testPolygonID] + "/face_visibility - " + to_string(wrapper->intermediateSteps) + "-"; } //Draw necessary things IOHandling::DrawCritical(vis->thePolygon, fileStringCrit); IOHandling::DrawArtGallery(vis->thePolygon, fileString, IP); } auto timeEnd = IOHandling::get_cpu_time(); chrono::duration time_span2 = chrono::duration_cast>(timeEnd - timeBegin); //Are we P5 (irrational polygon) if (wrapper->doingP5) { //track cumalative time chrono::duration time_span = chrono::duration_cast>(timeEnd - timePrev); wrapper->p5Times.push_back(time_span.count()); timePrev = timeEnd; //track Hausdorff. vector currentSolution; for (auto& vertex : IP.vertexSolution) currentSolution.push_back(vertex->point()); for (auto& face : IP.faceSolution) { auto eit = face->outer_ccb(); do { currentSolution.push_back(eit->source()->point()); } while (++eit != face->outer_ccb()); } //calculate Hausdorff and save... wrapper->hausdorffDistances.push_back(Hausdorff(p5Solution, currentSolution)); if (time_span2.count() >= wrapper->maxP5Time) break; //stop iterating! } else if (time_span2.count() >= 500) break; //print summary if (wrapper->inDrawMode) { cout << "----------- ITERATION " << wrapper->intermediateSteps << "\n"; /*cout << "WeakVisLookups so far: " << vis->weakvisLookups << "\n"; cout << "\n";*/ int j = 0; for (auto fit = IP.faceSolution.begin(); fit != IP.faceSolution.end(); fit++) { /* for (int i = 0; i < vis->weakVisibility.vis_polygons.size(); i++) IOHandling::DrawWeakVis(weakVisibility, "100-25/faceguardvis-" + to_string(wrapper->intermediateSteps) + "-" + to_string(i), faceToPolygon(f), Arrangement_2(), i);*/ //draw the weakvispolygon /*IOHandling::DrawWeakVis( vis->weakVisibility, fileStringFace + to_string(j), faceToPolygon(*fit), vis->facevisPolygons[(*fit)->data().id].container());*/ j++; } } //else //cout << " " << wrapper->intermediateSteps << " "; //cout << "Number of vertices: " << vis->thePolygon.number_of_vertices() << " "; wrapper->intermediateSteps++; } while (wrapper->intermediateSteps < wrapper->maxIterations && IP.bothFaces.size() > 0); auto timeEnd = IOHandling::get_cpu_time(); chrono::duration time_span = chrono::duration_cast>(timeEnd - timeBegin); wrapper->processingTime += time_span.count(); //General information wrapper->solutionSize = IP.vertexSolution.size(); wrapper->facesAtEnd = vis->thePolygon.number_of_faces() - 1; //no unbounded face wrapper->verticesAtEnd = vis->thePolygon.number_of_vertices(); //Count critical witnesses for (auto vit = vis->thePolygon.vertices_begin(); vit != vis->thePolygon.vertices_end(); vit++) if (vit->data().isCritical) wrapper->criticalVerticesAtEnd++; for (auto fit = vis->thePolygon.faces_begin(); fit != vis->thePolygon.faces_end(); fit++) if (fit->data().isCritical) wrapper->criticalFacesAtEnd++; //Decomp information wrapper->decompositionSize = weakVisRoot->subTreeSize() + 1; //this function recursively calculates subtreesize. wrapper->maxDecompVertices = weakVisRoot->maxVertices(); wrapper->maxDecompReflexVertices = weakVisRoot->maxReflexVertices(); //Visibility computations wrapper->constantLookups = vis->constantLookups; wrapper->faceVisibilitiesComputed = vis->faceVisibilitiesComputed; wrapper->pointVisibilitiesComputed = vis->pointVisibilitiesComputed; wrapper->weakvisLookups = vis->weakvisLookups; cout << "Clearing ILO memory\n"; IP.pointConstraints.end(); IP.faceConstraints.end(); IP.pointExpr.end(); IP.faceExpr.end(); IP.faceguardVar.end(); IP.pointguardVar.end(); IP.facewitnessVar.end(); IP.model.end(); IP.env.end(); vis->polygonBoundary.clear(); vis->thePolygon.clear(); return true; } }; ArtGallery::ArtGallery(int tId, int maxIterations, int criticalThreshold, bool useWeakVis, bool inTestMode, bool inDrawMode, int currentSize) { srand((unsigned int)time(0)); this->inTestMode = inTestMode; this->currentSize = currentSize; this->maxIterations = maxIterations; this->criticalThreshold = criticalThreshold; this->useWeakVis = useWeakVis; this->testPolygonID = tId; this->inDrawMode = inDrawMode; this->implementation = AGPTR(new ArtGalleryImpl(this)); //this->implementation = ArtGalleryImpl(this); } bool ArtGallery::initialize() { return implementation->initialize(); } bool ArtGallery::preProcess() { return implementation->preProcess(); } bool ArtGallery::iterations() { if (testPolygonID == 3 && currentSize == 1000 && !inDrawMode) return true; if (testPolygonID == 7 && currentSize == 1000 && !inDrawMode) return true; if (testPolygonID == 15 && currentSize == 1000 && !inDrawMode) return true; if (testPolygonID == 17 && currentSize == 1000 && !inDrawMode) return true; if (testPolygonID == 25 && currentSize == 1000 && !inDrawMode) return true; if (testPolygonID == 25 && currentSize == 100 && !inDrawMode) return true; if (testPolygonID == 18 && currentSize == 500) return true; implementation->iterations(); return true; } ArtGallery::~ArtGallery() { //this->implementation->~ArtGalleryImpl(); }