Point __trilaterate(const Circle& c1, const Circle& c2, const Circle& c3) { std::vector<Point> intersections; findIntersections(intersections,c1,c2); findIntersections(intersections,c1,c3); findIntersections(intersections,c2,c3); return polygonCentroid(intersections); }
void CubicBezierTimingFunction::partition(Vector<PartitionRegion>& regions) const { double solution1 = 0.0; double solution2 = 0.0; double solution3 = 0.0; size_t numberOfIntersections = findIntersections(0.5, solution1, solution2, solution3); // A valid cubic bezier should only cross the horizontal line // 1 or 3 times. switch (numberOfIntersections) { case 1: regions.append(PartitionRegion(TimingFunction::RangeHalf::Lower, 0.0, solution1)); regions.append(PartitionRegion(TimingFunction::RangeHalf::Upper, solution1, 1.0)); break; case 3: regions.append(PartitionRegion(TimingFunction::RangeHalf::Lower, 0.0, solution1)); regions.append(PartitionRegion(TimingFunction::RangeHalf::Upper, solution1, solution2)); regions.append(PartitionRegion(TimingFunction::RangeHalf::Lower, solution2, solution3)); regions.append(PartitionRegion(TimingFunction::RangeHalf::Upper, solution3, 1.0)); break; default: ASSERT_NOT_REACHED(); break; } }
void BVHSceneTree::getIntersections(Math::BoundsOBB const& bounds, std::vector<SceneObject*>& objects) const { objects.clear(); objects.reserve(m_AllObjects.size()); findIntersections(m_Root, bounds, objects); }
void BVHSceneTree::getIntersections(Math::Ray const& ray, std::vector<std::pair<SceneObject*, float>>& objects) const { //------------------------------------------------------------ // Find intersections and their distances from the origin. std::vector<std::pair<SceneObject*, float>> intersections; intersections.reserve(m_AllObjects.size()); findIntersections(m_Root, ray, intersections); //------------------------------------------------------------ // Sort the objects based on distance from origin. // This is done such that the object nearest the origin is first. std::sort(intersections.begin(), intersections.end(), [](std::pair<SceneObject*, float>& first, std::pair<SceneObject*, float>& second)->bool { return (first.second) < (second.second); }); //------------------------------------------------------------ // Return the sorted intersections objects.clear(); objects.reserve(intersections.size()); for(auto pair : intersections) { objects.emplace_back(pair); } }
void BVHSceneTree::findIntersections(BVHSceneNode* node, Math::BoundsOBB const& bounds, std::vector<SceneObject*>& objects) const { if(node) { if(bounds.intersects(node->bounds)) { if(node->type == SceneNodeType::Leaf) { objects.emplace_back(node->object); } else { findIntersections(node->left, bounds, objects); findIntersections(node->right, bounds, objects); } } } }
void BVHSceneTree::findIntersections(BVHSceneNode* node, Math::BoundsSphere const& bounds, std::vector<SceneObject*>& objects) const { if(node) { if(bounds.intersects(node->bounds)) { if((node->type == SceneNodeType::Leaf) && (node->object)) { objects.emplace_back(node->object); } else { findIntersections(node->left, bounds, objects); findIntersections(node->right, bounds, objects); } } // Do nothing if there is no intersection. } }
void BVHSceneTree::findIntersections(BVHSceneNode* node, Math::Ray const& ray, std::vector<std::pair<SceneObject*, float>>& objects) const { if(node) { Math::Vector3f point; float distance; if(ray.intersects(node->bounds, point, distance)) { if((node->type == SceneNodeType::Leaf) && (node->object)) { objects.emplace_back(std::make_pair(node->object, distance)); } else { findIntersections(node->left, ray, objects); findIntersections(node->right, ray, objects); } } } }
void TRegion::Imp::computeScanlineIntersections(double y, vector<double> &intersections) const { TRectD bbox = getBBox(); if (y <= bbox.y0 || y >= bbox.y1) return; assert(intersections.empty()); UINT i, firstSide = 0; vector<int> sides; for (i = 0; i < m_edge.size(); i++) { TEdge *e = m_edge[i]; TStroke *s = e->m_s; if (s->getBBox().y0 > y || s->getBBox().y1 < y) continue; int chunkIndex0, chunkIndex1; double t0, t1; s->getChunkAndT(e->m_w0, chunkIndex0, t0); s->getChunkAndT(e->m_w1, chunkIndex1, t1); if (chunkIndex0 > chunkIndex1) { findIntersections(y, *s->getChunk(chunkIndex0), t0, 0, intersections, sides); for (int j = chunkIndex0 - 1; j > chunkIndex1; j--) findIntersections(y, *s->getChunk(j), 1, 0, intersections, sides); findIntersections(y, *s->getChunk(chunkIndex1), 1, t1, intersections, sides); } else if (chunkIndex0 < chunkIndex1) { findIntersections(y, *s->getChunk(chunkIndex0), t0, 1, intersections, sides); for (int j = chunkIndex0 + 1; j < chunkIndex1; j++) findIntersections(y, *s->getChunk(j), 0, 1, intersections, sides); findIntersections(y, *s->getChunk(chunkIndex1), 0, t1, intersections, sides); } else { findIntersections(y, *s->getChunk(chunkIndex0), t0, t1, intersections, sides); } } if (intersections.size() > 0 && intersections.front() == intersections.back()) { intersections.pop_back(); if (!sides.empty() && sides.front() == sides.back() && intersections.size() > 0) intersections.erase(intersections.begin()); } std::sort(intersections.begin(), intersections.end()); assert(intersections.size() % 2 == 0); }
/** * Calculate the Y and E values for the given possible overlap * @param inputWS :: A pointer to the inputWS * @param newPoly :: A reference to a polygon to test for overlap * @returns A pair of Y and E values */ std::pair<double,double> SofQW2::calculateYE(API::MatrixWorkspace_const_sptr inputWS, const ConvexPolygon & newPoly) const { // Build a list intersection locations in terms of workspace indices // along with corresponding weights from that location std::vector<BinWithWeight> overlaps = findIntersections(inputWS, newPoly); std::pair<double,double> binValues(0,0); if( inputWS->isDistribution() ) { const double newWidth = newPoly[3].X() - newPoly[0].X(); // For distribution binValues = calculateDistYE(inputWS, overlaps, newWidth); } else { binValues = calculateYE(inputWS, overlaps); } return binValues; }
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , m_update_pending(false), m_animating(false) , m_fgColor(255, 255, 255), m_bgColor(0, 0, 0) { m_oglviewer = new OGLViewer; ui.setupUi(this); ui.ogl_layout->addWidget(m_oglviewer); //setWindowTitle(tr("OpenGL Qt Template")); m_oglviewer->setFocusPolicy(Qt::StrongFocus); connect(ui.clear_button, SIGNAL(clicked()), m_oglviewer, SLOT(clearVertex())); connect(ui.curve_type, SIGNAL(currentIndexChanged(int)), m_oglviewer, SLOT(changeCurveType(int))); connect(ui.degree_val, SIGNAL(valueChanged(int)), m_oglviewer, SLOT(setDegree(int))); connect(ui.seg_val, SIGNAL(valueChanged(int)), m_oglviewer, SLOT(setSegment(int))); connect(ui.actionOpen, SIGNAL(triggered()), this, SLOT(readPoints())); connect(ui.actionSave, SIGNAL(triggered()), this, SLOT(savePoints())); connect(ui.actionExport, SIGNAL(triggered()), this, SLOT(exportSVG())); signalMapper = new QSignalMapper(this); connect(signalMapper, SIGNAL(mapped(int)), m_oglviewer, SLOT(changeOperation(int))); signalMapper->setMapping(ui.actionInsert, 0); signalMapper->setMapping(ui.actionMove, 1); connect(ui.actionInsert, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(ui.actionMove, SIGNAL(triggered()), signalMapper, SLOT(map())); connect(ui.intersection_button, SIGNAL(clicked()), m_oglviewer, SLOT(findIntersections())); connect(ui.disp_ctrl_pts, SIGNAL(toggled(bool)), m_oglviewer, SLOT(setDispCtrlPts(bool))); connect(ui.disp_curves, SIGNAL(toggled(bool)), m_oglviewer, SLOT(setDispCurves(bool))); connect(ui.disp_intersections, SIGNAL(toggled(bool)), m_oglviewer, SLOT(setDispIntersections(bool))); ui.foreground_color->setStyleSheet("QPushButton { background-color : #FFFFFF;}"); ui.background_color->setStyleSheet("QPushButton { background-color : #000000;}"); connect(ui.foreground_color, SIGNAL(clicked()), this, SLOT(pickColor())); }
/* * Vertex positioning is based on [Kobbelt et al, 2001] */ float Octree::findVertex(Evaluator* e) { findIntersections(e); // Find the center of intersection positions glm::vec3 center = std::accumulate( intersections.begin(), intersections.end(), glm::vec3(), [](const glm::vec3& a, const Intersection& b) { return a + b.pos; }) / float(intersections.size()); /* The A matrix is of the form * [n1x, n1y, n1z] * [n2x, n2y, n2z] * [n3x, n3y, n3z] * ... * (with one row for each Hermite intersection) */ Eigen::MatrixX3f A(intersections.size(), 3); for (unsigned i=0; i < intersections.size(); ++i) { auto d = intersections[i].norm; A.row(i) << Eigen::Vector3f(d.x, d.y, d.z).transpose(); } /* The B matrix is of the form * [p1 . n1] * [p2 . n2] * [p3 . n3] * ... * (with one row for each Hermite intersection) * * Positions are pre-emtively shifted so that the center of the contoru * is at 0, 0, 0 (since the least-squares fix minimizes distance to the * origin); we'll unshift afterwards. */ Eigen::VectorXf B(intersections.size(), 1); for (unsigned i=0; i < intersections.size(); ++i) { B.row(i) << glm::dot(intersections[i].norm, intersections[i].pos - center); } // Use singular value decomposition to solve the least-squares fit. Eigen::JacobiSVD<Eigen::MatrixX3f> svd(A, Eigen::ComputeFullU | Eigen::ComputeFullV); // Truncate singular values below 0.1 auto singular = svd.singularValues(); svd.setThreshold(0.1 / singular.maxCoeff()); rank = svd.rank(); // Solve the equation and convert back to cell coordinates Eigen::Vector3f solution = svd.solve(B); vert = glm::vec3(solution.x(), solution.y(), solution.z()) + center; // Clamp vertex to be within the bounding box vert.x = std::min(X.upper(), std::max(vert.x, X.lower())); vert.y = std::min(Y.upper(), std::max(vert.y, Y.lower())); vert.z = std::min(Z.upper(), std::max(vert.z, Z.lower())); // Find and return QEF residual auto m = A * solution - B; return m.transpose() * m; }
// Perform clipping of the polygon clip with nc points against // a subject with ns points. Returns a set of nl polygons with specified lengths // in an array of coordinates polys. int clip(double *clipx, double *clipy, int nc, double *subjectx, double *subjecty, int ns, double **polysx, double **polysy, int **origin, int **lengths, int *nl, int *nlp, int *inside, int op) { struct vertex *lclip, *lsubject; struct vertex *polygons = NULL, *polygons2 = NULL, *auxpoly = NULL; int cIntExt=0, sIntExt=0; int nvertex, nvertex2, npolys, npolys2; // create data structures createList(1,clipx, clipy, nc, &lclip); createList(2,subjectx, subjecty, ns, &lsubject); //printf("created lists\n"); // phase one of the algorithm findIntersections(lclip, lsubject); //printf("found intersections\n"); switch(op) { case POLYGON_UNION: cIntExt = sIntExt = POLYGON_INTERIOR; break; case POLYGON_INTERSECTION: cIntExt = sIntExt = POLYGON_EXTERIOR; break; case POLYGON_DIFF_AB: cIntExt = POLYGON_EXTERIOR; sIntExt = POLYGON_INTERIOR; break; case POLYGON_XOREXT: cIntExt = POLYGON_EXTERIOR; sIntExt = POLYGON_INTERIOR; break; case POLYGON_DIFF_BA: cIntExt = POLYGON_INTERIOR; sIntExt = POLYGON_EXTERIOR; break; } markEntries(lclip, lsubject, sIntExt); markEntries(lsubject, lclip, cIntExt); //printf("marked entries\n"); // phase three of the algorithm npolys = createClippedPolygon(lclip, lsubject, &polygons, &nvertex); if(op==POLYGON_XOREXT && npolys > 0) { cIntExt = POLYGON_INTERIOR; sIntExt = POLYGON_EXTERIOR; markEntries(lclip, lsubject, sIntExt); markEntries(lsubject, lclip, cIntExt); npolys2 = createClippedPolygon(lclip, lsubject, &polygons2, &nvertex2); // number of "positive" polygons: *nlp = npolys; npolys += npolys2; nvertex += nvertex2; auxpoly = polygons; while(auxpoly->nextPoly) auxpoly = auxpoly->nextPoly; auxpoly->nextPoly = polygons2; } else { // only xorext operation uses nlp: *nlp = 0; } //printf("clip polygon\n"); // copy polygons into polys array copy(polygons, npolys, nvertex, polysx, polysy, origin, lengths); *nl = npolys; //printf("copied\n"); *inside = 0; if (isInside(lclip,lsubject)) *inside = 1; if (isInside(lsubject,lclip)) *inside = 2; // free memory deleteList(lclip); deleteList(lsubject); deletePolygons(polygons); return 0; }
/// The main clipping function std::vector<UPolygon*> clip(UPolygon* p0, UPolygon* p1) { //Step one is to identify all of the intersection points between the two UPolygon; findIntersections(p1,p0); std::vector<UPolygon*> polygons;// = new std::vector<UPolygon*>(); NAME names[2] = {p0->name, p1->name}; // get next entering intersection PointNode* entering = findEnteringIntersection(p1->pointList, p1->name); while (entering != NULL) { UPolygon* newPoly = new UPolygon(CLIP); PointNode* current = entering; int currentPoly = 1; while (false == current->visited) { newPoly->addPoint(current->x, current->y); current->visited = true; if (current->isIntersection(names[currentPoly]) && current != entering) currentPoly = (currentPoly + 1) % 2; current = current->next[names[currentPoly]]; if (current == NULL) { // time to wrap if (currentPoly == 0) current = p0->pointList; else current = p1->pointList; } } polygons.push_back(newPoly); entering = findEnteringIntersection(current->next[p1->name], p1->name); } if (polygons.size() == 0) { /* # we found no polygons - possibly one is contained in the other # first check to see if our clipping region contains the other one # theoretically, any point will do, except that all of the end # points might intersect the boundary of the shape - and thus fail # the containment test. So, we pick a point that is halfway along # the first edge and one unit vector in the direction opposite the # perp vector */ PointNode* A = p1->pointList; PointNode* B = p1->pointList->next[p1->name]; Vector b = *B - *A; Vector b_perp = b.perp(); b_perp.normalize(); int x = .5 * (A->x + B->x) - b_perp.x; int y = .5 * (A->y + B->y) - b_perp.y; if (p0->contains(x,y)) { // make a copy of poly0 UPolygon* newPoly = new UPolygon(SUBJECT); PointNode* pt = p0->pointList; while(pt != NULL) { newPoly->addPoint(pt->x,pt->y); pt = pt->next[p0->name]; } polygons.push_back(newPoly); } // now check to see if the clipping region is enclosed by the other else { PointNode* A = p0->pointList; PointNode* B = p0->pointList->next[p0->name]; Vector b = *B - *A; Vector b_perp = b.perp(); b_perp.normalize(); x = .5 * (A->x + B->x) - b_perp.x; y = .5 * (A->y + B->y) - b_perp.y; if (p1->contains(x,y)) { // make a copy of poly0 UPolygon* newPoly = new UPolygon(SUBJECT); PointNode* pt = p1->pointList; while(pt != NULL) { newPoly->addPoint(pt->x,pt->y); pt = pt->next[p1->name]; } polygons.push_back(newPoly); } else //return two base polygons { polygons.push_back(p0); polygons.push_back(p1); } } } return polygons; }
void ConvexPolygon::booleanDifference(const ConvexPolygon &hole, std::vector<ConvexPolygon> &list) const { // Special case: this polygon is entirely swallowed by the hole if(hole.envelopes(*this)) return; // Special case: the hole is entirely inside this polygon if(envelopes(hole)) { Points p1, p2; splitPolygon(*this, hole, p1, p2); ConvexPolygon::make(p1, list); ConvexPolygon::make(p2, list); return; } // Common case: hole intersects with this polygon. std::vector<bool> visited(vertexCount()); std::queue<unsigned int> queue; queue.push(0); // Perform intersection unsigned int oldsize = list.size(); Points poly; while(!queue.empty()) { int i = queue.front(); while(i < vertexCount()) { // Stop if we've already been here if(visited[i]) break; visited[i] = true; // Include point if it is not inside the hole bool inhole = hole.hasPoint(vertex(i)); if(!inhole) poly.push_back(vertex(i)); // Check for intersections Point isect[2]; int isectv[2]; findIntersections(*this, i, i+1, hole, isect, isectv); if(isectv[0] >= 0) { // Intersection found: this is the start of a hole, // except when this edge started inside the hole. poly.push_back(isect[0]); if(!inhole) { // Start tracing the hole int j = isectv[0]; do { // Check for intersections // The first hole edge may intersect with another edges Point hisect[2]; int hisectv[2]; findIntersections(hole, j+1, j, *this, hisect, hisectv); // There is always one intersection (the one that got us here) if((j == isectv[0] && hisectv[1] >= 0) || (j != isectv[0] && hisectv[0] >= 0)) { // Pick the intersection that is not the one we came in on Point ip; int iv; if(hisectv[1] < 0 || glm::distance2(hisect[0],isect[0]) > glm::distance(hisect[1],isect[0])) { ip = hisect[0]; iv = hisectv[0]; } else { ip = hisect[1]; iv = hisectv[1]; } queue.push(i+1); // Avoid adding duplicate point of origin if(glm::distance2(poly.front(), ip) > 0.0001) poly.push_back(ip); i = iv; break; } else { // No intersections? Just add the hole vertex then poly.push_back(hole.vertex(j)); } if(--j < 0) j = hole.vertexCount() - 1; } while(j != isectv[0]); } } ++i; } // Partition the generated polygon into convex polygons // and add them to the list. if(poly.size() >= 3) { try { ConvexPolygon::make(poly, list); } catch(const algorithm::GeometryException &e) { // Bad polygons generated... The algorithm works well // enough most of the time, let's just roll back the error. int changes = list.size() - oldsize; #ifndef NDEBUG cerr << "booleanDifference error: " << e.what() << " (" << changes << " change(s) rolled back)\n"; #endif while(changes-->0) list.pop_back(); list.push_back(*this); return; } } poly.clear(); queue.pop(); } }