void testInCirclePredicate() { double pa[2] = {-2,0}; double pb[2] = {2,0}; double pc[2] = {0,3}; double pd[2] = {0,1.5}; double pdp[2] = {0,-1.5}; double pbc[2] = {3,2}; double pca[2] = {-3,-3}; double rtn = incircle(pa,pb,pc,pd); double rtn1 = incircle(pa,pb,pc,pdp); double rtnbc = incircle(pa,pb,pc,pca); // The following test case is the incircle test! double p25_4_41_v0[2] = {0.657466,2.696793}; double p25_4_41_v1[2] = {2.000000,2.000000}; double p25_4_41_v2[2] = {1.354103,1.967425}; double p25_4_25_v[2] = {0.657466,2.696793}; double p25_4_25_incircle = incircle(p25_4_41_v0,p25_4_41_v1,p25_4_41_v2,p25_4_25_v); double p641_1996_1069_v0[2] = {1.784130,2.094302}; double p641_1996_1069_v1[2] = {1.285546,2.383407}; double p641_1996_1069_v2[2] = {1.400998,2.373647}; double p641_1996_2333_v[2] = {1.400165,2.265218}; double p641_1996_1069_incircle = incircle(p641_1996_1069_v0,p641_1996_1069_v1,p641_1996_1069_v2,p641_1996_2333_v); }
/*! * \param globalverts global vertices vector * \param v1 first vertex * \param v2 second vertex * \param v3 third vertex * \param p the point * \return 0 if not inside <BR> * 1 if inside <BR> */ int SimplePolygon::isInsideCircumCircle( DCTPVec2dvector &globalverts, int v1, int v2, int v3, int p ) const { double pa[2], pb[2], pc[2], pd[2]; pa [ 0 ] = globalverts[ vertices[ v1 ] ][0]; pa [ 1 ] = globalverts[ vertices[ v1 ] ][1]; pb [ 0 ] = globalverts[ vertices[ v2 ] ][0]; pb [ 1 ] = globalverts[ vertices[ v2 ] ][1]; pc [ 0 ] = globalverts[ vertices[ v3 ] ][0]; pc [ 1 ] = globalverts[ vertices[ v3 ] ][1]; pd [ 0 ] = globalverts[ vertices[ p ] ][0]; pd [ 1 ] = globalverts[ vertices[ p ] ][1]; // check for order of (pa, pb, pc) they must be in counterclockwise order double order = orient2d( pa, pb, pc ); double dres; if ( order < 0.0 ) // clockwise order -> change order dres = incircle( pa, pc, pb, pd ); else dres = incircle( pa, pb, pc, pd ); //std::cerr << pa[ 0 ] << "," << pa[ 1 ] << " "; //std::cerr << pb[ 0 ] << "," << pb[ 1 ] << " "; //std::cerr << pc[ 0 ] << "," << pc[ 1 ] << " "; //std::cerr << pd[ 0 ] << "," << pd[ 1 ] << std::endl; //std::cerr << "Inside Circumcircle: " << dres << std::endl; // >0 if inside if ( dres <= 0 ) return 0; else return 1; }
// InsertVertex in the paper static void insert_cavity_vertex_helper(MutableTriangleTopology& mesh, RawField<const Perturbed2,VertexId> X, RawField<bool,VertexId> marked, const HalfedgeId vw) { // If wv is a boundary edge, or we're already Delaunay and properly oriented, we're done const auto wv = mesh.reverse(vw); if (mesh.is_boundary(wv)) return; const auto u = mesh.opposite(vw), v = mesh.src(vw), w = mesh.dst(vw), x = mesh.opposite(wv); const auto Xu = X[u], Xv = X[v], Xw = X[w], Xx = X[x]; const bool in = incircle(Xu,Xv,Xw,Xx); if (!in && triangle_oriented(Xu,Xv,Xw)) return; // Flip edge and recurse const auto xu = mesh.flip_edge(wv); assert(mesh.vertices(xu)==vec(x,u)); const auto vx = mesh.prev(xu), xw = mesh.next(mesh.reverse(xu)); // Grab this now before the recursive call changes uvx insert_cavity_vertex_helper(mesh,X,marked,vx), insert_cavity_vertex_helper(mesh,X,marked,xw); if (!in) marked[u] = marked[v] = marked[w] = marked[x] = true; }
Exact_adaptive_kernel::Oriented_side Exact_adaptive_kernel::oriented_circle (Point2 const& pa, Point2 const& pb, Point2 const& pc, Point2 const& test) { double r = incircle(pa.coord(), pb.coord(), pc.coord(), test.coord()); if (r > 0.0) return ON_POSITIVE_SIDE; else if (r < 0.0) return ON_NEGATIVE_SIDE; else return ON_ORIENTED_BOUNDARY; }
int main(int argc, char *argv[]) { FILE *fp; float cx, cy, r, px, py; fp = fopen(*++argv, "r"); while (fscanf(fp, "Center: (%f, %f); Radius: %f; Point: (%f, %f)\n", &cx, &cy, &r, &px, &py) != EOF) { if (incircle(cx - px, cy - py, r)) { puts("true"); } else { puts("false"); } } return 0; }
static void predicate_tests() { IntervalScope scope; typedef Vector<double,2> TV2; typedef Vector<Quantized,2> QV2; // Compare triangle_oriented and incircle against approximate floating point versions struct F { static inline double triangle_oriented(const TV2 p0, const TV2 p1, const TV2 p2) { return edet(p1-p0,p2-p0); }; static inline double incircle(const TV2 p0, const TV2 p1, const TV2 p2, const TV2 p3) { const auto d0 = p0-p3, d1 = p1-p3, d2 = p2-p3; return edet(ROW(d0),ROW(d1),ROW(d2)); } }; const auto random = new_<Random>(9817241); for (int step=0;step<100;step++) { #define MAKE(i) \ const auto p##i = tuple(i,QV2(random->uniform<Vector<ExactInt,2>>(-exact::bound,exact::bound))); \ const TV2 x##i(p##i.y); MAKE(0) MAKE(1) MAKE(2) MAKE(3) GEODE_ASSERT(triangle_oriented(p0,p1,p2)==(F::triangle_oriented(x0,x1,x2)>0)); GEODE_ASSERT(incircle(p0,p1,p2,p3)==(F::incircle(x0,x1,x2,x3)>0)); } // Test behavior for large numbers, using the scale invariance and antisymmetry of incircle. for (const int i : range(exact::log_bound)) { const auto bound = ExactInt(1)<<i; const auto p0 = tuple(0,QV2(-bound,-bound)), // Four points on a circle of radius sqrt(2)*bound p1 = tuple(1,QV2( bound,-bound)), p2 = tuple(2,QV2( bound, bound)), p3 = tuple(3,QV2(-bound, bound)); GEODE_ASSERT(!incircle(p0,p1,p2,p3)); GEODE_ASSERT( incircle(p0,p1,p3,p2)); } }
// Test whether an edge is Delaunay GEODE_ALWAYS_INLINE static inline bool is_delaunay(const TriangleTopology& mesh, RawField<const Perturbed2,VertexId> X, const HalfedgeId edge) { // Boundary edges belong to the sentinel quad and are always Delaunay. const auto rev = mesh.reverse(edge); if (mesh.is_boundary(rev)) return true; // Grab vertices in counterclockwise order const auto v0 = mesh.src(edge), v1 = mesh.src(mesh.prev(rev)), v2 = mesh.dst(edge), v3 = mesh.src(mesh.prev(edge)); const auto x0 = X[v0], x1 = X[v1], x2 = X[v2], x3 = X[v3]; // If we have a nonsentinel interior edge, perform a normal incircle test if (maxabs(x0.value().x,x1.value().x,x2.value().x,x3.value().x)!=bound) return !incircle(x0,x1,x2,x3); // Fall back to sentinel case analysis return is_delaunay_sentinels(x0,x1,x2,x3); }
// Delaunay retriangulate a triangle fan static void chew_fan(MutableTriangleTopology& parent_mesh, RawField<const Perturbed2,VertexId> X, const VertexId u, RawArray<HalfedgeId> fan, Random& random) { chew_fan_count_ += 1; #ifndef NDEBUG for (const auto e : fan) assert(parent_mesh.opposite(e)==u); for (int i=0;i<fan.size()-1;i++) GEODE_ASSERT(parent_mesh.src(fan[i])==parent_mesh.dst(fan[i+1])); #endif const int n = fan.size(); if (n < 2) return; chew_fan_count_ += 1024*n; // Collect vertices const Field<VertexId,VertexId> vertices(n+2,uninit); vertices.flat[0] = u; vertices.flat[1] = parent_mesh.src(fan[n-1]); for (int i=0;i<n;i++) vertices.flat[i+2] = parent_mesh.dst(fan[n-1-i]); // Delete original vertices for (const auto e : fan) parent_mesh.erase(parent_mesh.face(e)); // Make the vertices into a doubly linked list const Field<VertexId,VertexId> prev(n+2,uninit), next(n+2,uninit); prev.flat[0].id = n+1; next.flat[n+1].id = 0; for (int i=0;i<n+1;i++) { prev.flat[i+1].id = i; next.flat[i].id = i+1; } // Randomly shuffle the vertices, then pulling elements off the linked list in reverse order of our final shuffle. const Array<VertexId> pi(n+2,uninit); for (int i=0;i<n+2;i++) pi[i].id = i; random.shuffle(pi); for (int i=n+1;i>=0;i--) { const auto j = pi[i]; prev[next[j]] = prev[j]; next[prev[j]] = next[j]; } // Make a new singleton mesh const auto mesh = new_<MutableTriangleTopology>(); mesh->add_vertices(n+2); small_sort(pi[0],pi[1],pi[2]); mesh->add_face(vec(pi[0],pi[1],pi[2])); // Insert remaining vertices Array<HalfedgeId> work; for (int i=3;i<n+2;i++) { const auto j = pi[i]; const auto f = mesh->add_face(vec(j,next[j],prev[j])); work.append(mesh->reverse(mesh->opposite(f,j))); while (work.size()) { auto e = work.pop(); if ( !mesh->is_boundary(e) && incircle(X[vertices[mesh->src(e)]], X[vertices[mesh->dst(e)]], X[vertices[mesh->opposite(e)]], X[vertices[mesh->opposite(mesh->reverse(e))]])) { work.append(mesh->reverse(mesh->next(e))); work.append(mesh->reverse(mesh->prev(e))); e = mesh->unsafe_flip_edge(e); } } } // Copy triangles back to parent for (const auto f : mesh->faces()) { const auto vs = mesh->vertices(f); parent_mesh.add_face(vec(vertices[vs.x],vertices[vs.y],vertices[vs.z])); } }
/*! * Note that the resulting triangulation will not necessarily be complex, * since it's constrained by the polygon's edges. * * Besides triangulating the polygon this method also does: * - insertion of the new polygons (triangles) at the end of * the polygon list. * - setting up marking information for the new polygons. * * \param polylist the global list of polygons * \param selfindex the index of this polygon in the global list * \return zero on success, and a negative integer if some error occured. */ int SimplePolygon::triangulate( DCTPVec2dvector &globalverts, simplepolygonvector &polylist) { #ifdef OSG_TRIANGULATE_CONVEX if( ( !is_marked ) && ( m_bConvex ) ) { // std::cerr <<"triangulating convex: " <<vertices.size() << std::endl; switch( vertices.size( ) ) { case 0: case 1: case 2: return 0; case 3: { polylist.push_back( *this ); } return 0; } unsigned int ui_prev; unsigned int ui_mid; unsigned int ui_next; const unsigned int cui_vertex_cnt = vertices.size( ); SimplePolygon cl_poly; ui_mid = 0; for( ui_prev = 1; ui_prev < cui_vertex_cnt; ++ui_prev ) { if( globalverts[ vertices[ ui_prev ] ][1] < globalverts[ vertices[ ui_mid ] ][1] ) { ui_mid = ui_prev; } else if( ( globalverts[ vertices[ ui_prev ] ][1] == globalverts[ vertices[ ui_mid ] ][1] ) && ( globalverts[ vertices[ ui_prev ] ][0] < globalverts[ vertices[ ui_mid ] ][0] ) ) { ui_mid = ui_prev; } } ui_prev = ( ui_mid + cui_vertex_cnt - 1 ) % cui_vertex_cnt; ui_next = ( ui_mid + 1 ) % cui_vertex_cnt; cl_poly.vertices.resize( 3 ); cl_poly.is_marked = is_marked; cl_poly.vertices[ 0 ] = vertices[ ui_mid ]; cl_poly.vertices[ 1 ] = vertices[ ui_next ]; cl_poly.vertices[ 2 ] = vertices[ ui_prev ]; ui_prev = ( ui_prev + cui_vertex_cnt - 1 ) % cui_vertex_cnt; ui_next = ( ui_next + 1 ) % cui_vertex_cnt; while( cl_poly.vertices[ 1 ] != cl_poly.vertices[ 2 ] ) { polylist.push_back( cl_poly ); if( globalverts[ vertices[ ui_prev ] ][1] < globalverts[ vertices[ ui_next ] ][1] ) { cl_poly.vertices[ 0 ] = cl_poly.vertices[ 2 ]; cl_poly.vertices[ 2 ] = vertices[ ui_prev ]; ui_prev = ( ui_prev + cui_vertex_cnt - 1 ) % cui_vertex_cnt; } else if( ( globalverts[ vertices[ ui_prev ] ][1] == globalverts[ vertices[ ui_next ] ][1] ) && ( globalverts[ vertices[ ui_prev ] ][0] < globalverts[ vertices[ ui_next ] ][0] ) ) { cl_poly.vertices[ 0 ] = cl_poly.vertices[ 2 ]; cl_poly.vertices[ 2 ] = vertices[ ui_prev ]; ui_prev = ( ui_prev + cui_vertex_cnt - 1 ) % cui_vertex_cnt; } else { cl_poly.vertices[ 0 ] = cl_poly.vertices[ 1 ]; cl_poly.vertices[ 1 ] = vertices[ ui_next ]; ui_next = ( ui_next + 1 ) % cui_vertex_cnt; } } return 0; } #endif // std::cerr << " triangulate in, size: " << vertices.size() << std::endl; switch( vertices.size( ) ) { case 0: case 1: case 2: return 0; case 3: { polylist.push_back( *this ); // SimplePolygon p; // p.vertices = vertices; // p.is_marked = is_marked; // std::cerr << "adding polygon of 3 vertices into the list..." << std::endl; // polylist.push_back( p ); // FIXME, this is not too elegant // std::cerr << "triangulate out!!!" << std::endl; } return 0; case 4: { const int ci_v1 = vertices[ 0 ]; const int ci_v2 = vertices[ 1 ]; const int ci_v3 = vertices[ 2 ]; const int ci_v4 = vertices[ 3 ]; const double cd_sdist1 = ( globalverts[ ci_v1 ] - globalverts[ ci_v3 ] ).squareLength( ); const double cd_sdist2 = ( globalverts[ ci_v2 ] - globalverts[ ci_v4 ] ).squareLength( ); double ad_pa[ 2 ]; double ad_pb[ 2 ]; double ad_pc[ 2 ]; double ad_pd[ 2 ]; SimplePolygon p; p.vertices.resize( 3 ); p.is_marked = is_marked; ad_pa[ 0 ] = globalverts[ ci_v1 ][0]; ad_pa[ 1 ] = globalverts[ ci_v1 ][1]; ad_pb[ 0 ] = globalverts[ ci_v2 ][0]; ad_pb[ 1 ] = globalverts[ ci_v2 ][1]; ad_pc[ 0 ] = globalverts[ ci_v3 ][0]; ad_pc[ 1 ] = globalverts[ ci_v3 ][1]; ad_pd[ 0 ] = globalverts[ ci_v4 ][0]; ad_pd[ 1 ] = globalverts[ ci_v4 ][1]; if( cd_sdist1 - cd_sdist2 < DCTP_EPS ) { /* const double cd_r1 = orient2d( ad_pa, ad_pb, ad_pc ); const double cd_r2 = orient2d( ad_pa, ad_pb, ad_pd ); if( ( ( cd_r1 <= 0.0 ) && ( cd_r2 <= 0.0 ) ) || ( ( cd_r1 >= 0.0 ) && ( cd_r2 >= 0.0 ) ) )*/ if( ( orient2d( ad_pa, ad_pb, ad_pc ) <= 0.0 ) || ( orient2d( ad_pa, ad_pd, ad_pc ) >= 0.0 ) || ( incircle( ad_pa, ad_pb, ad_pc, ad_pd ) > 0.0 ) ) { p.vertices[ 0 ] = ci_v1; p.vertices[ 1 ] = ci_v2; p.vertices[ 2 ] = ci_v4; polylist.push_back( p ); p.vertices[ 0 ] = ci_v2; p.vertices[ 1 ] = ci_v3; p.vertices[ 2 ] = ci_v4; polylist.push_back( p ); // std::cerr << globalverts[ ci_v1 ] << globalverts[ ci_v2 ] << globalverts[ ci_v3 ] << globalverts[ ci_v4 ] << std::endl; } else { p.vertices[ 0 ] = ci_v1; p.vertices[ 1 ] = ci_v2; p.vertices[ 2 ] = ci_v3; polylist.push_back( p ); p.vertices[ 0 ] = ci_v1; p.vertices[ 1 ] = ci_v3; p.vertices[ 2 ] = ci_v4; polylist.push_back( p ); } } else { // const double cd_r1 = orient2d( ad_pc, ad_pd, ad_pa ); // const double cd_r2 = orient2d( ad_pc, ad_pd, ad_pb ); // if( ( ( cd_r1 <= 0.0 ) && ( cd_r2 <= 0.0 ) ) || // ( ( cd_r1 >= 0.0 ) && ( cd_r2 >= 0.0 ) ) ) if( ( orient2d( ad_pb, ad_pc, ad_pd ) <= 0.0 ) || ( orient2d( ad_pb, ad_pa, ad_pd ) >= 0.0 ) || ( incircle( ad_pa, ad_pb, ad_pd, ad_pc ) > 0.0 ) ) { p.vertices[ 0 ] = ci_v1; p.vertices[ 1 ] = ci_v2; p.vertices[ 2 ] = ci_v3; polylist.push_back( p ); p.vertices[ 0 ] = ci_v1; p.vertices[ 1 ] = ci_v3; p.vertices[ 2 ] = ci_v4; polylist.push_back( p ); // std::cerr << globalverts[ ci_v1 ] << globalverts[ ci_v2 ] << globalverts[ ci_v3 ] << globalverts[ ci_v4 ] << std::endl; } else { p.vertices[ 0 ] = ci_v1; p.vertices[ 1 ] = ci_v2; p.vertices[ 2 ] = ci_v4; polylist.push_back( p ); p.vertices[ 0 ] = ci_v2; p.vertices[ 1 ] = ci_v3; p.vertices[ 2 ] = ci_v4; polylist.push_back( p ); } } } return 0; } // recalc valid third points! v1tp = -1; validThirdPoints.resize( vertices.size( ) ); SimplePolygon poly; int i2, i3; // this is an index into the vertices[] vector int err; DCTPivector verts; //p1verts, p2verts, p3verts; int i; int j; // pseudo random (reproduces same triangulation) int offs = ( int( globalverts[ vertices[ 0 ] ][0] * vertices.size( ) ) ) % vertices.size( ); /* for( i = 0; i < vertices.size( ); ++i ) { std::cerr << globalverts[ vertices[ i ] ][0] << ","; std::cerr << globalverts[ vertices[ i ] ][1] << std::endl; }*/ for( j = 0; j < int(vertices.size()); j++ ) { i = ( j + offs ) % vertices.size( ); // v1 = vertices[ i ]; if ( i == int(vertices.size()) - 1 ) i2 = 0; //v2 = vertices [ 0 ]; else i2 = i + 1; //v2 = vertices[ i + 1 ]; err = findThirdPoint( globalverts, i, i2, i3 ); if ( err ) return err; if ( i3 >= 0 ) { // build p1 int k = i2; // !!! verts.resize( 0 ); while ( k != i3 ) { // std::cerr << " k: " << k; verts.push_back( vertices[ k ] ); k++; if ( k == int(vertices.size()) ) k = 0; } // while k verts.push_back( vertices[ k ] ); // record the last one aswell // std::cerr << " k: " << k << std::endl; poly.vertices = verts; poly.is_marked = is_marked; // std::cerr << "calling p1... " << std::endl; err = poly.triangulate( globalverts, polylist); if ( err ) return err; // build p2 verts.resize( 3 ); verts[ 0 ] = vertices[ i ]; verts[ 1 ] = vertices[ i2 ]; verts[ 2 ] = vertices[ i3 ]; poly.vertices = verts; poly.is_marked = is_marked; // std::cerr << "adding p2 to the list..." << std::endl; polylist.push_back( poly ); // build p3 k = i3; verts.resize( 0 ); while ( k != i ) { verts.push_back( vertices[ k ] ); k++; if ( k == int(vertices.size()) ) k = 0; } // while k verts.push_back( vertices[ k ] ); // record the last one aswell poly.vertices = verts; poly.is_marked = is_marked; // std::cerr << "calling p3... " << std::endl; err = poly.triangulate( globalverts, polylist ); if ( err ) return err; // std::cerr << "triangulate out!!!" << std::endl; return 0; } // if } // for i /* SWARNING << "triangulate out WITH ERROR!!!" << endLog; for( i = 0; i < vertices.size( ); ++i ) { std::cerr << globalverts[ vertices[ i ] ][0] << ","; std::cerr << globalverts[ vertices[ i ] ][1] << std::endl; }*/ // char x[ 256 ]; // gets( x ); return -1; }
int main(){ double f = 3; printf("rand: %f\n",incircle(&f,&f,&f,&f)); }
/*Type of Cut Strategy is defined as: * (useAltCut, useVertical) = (true, true) => Alternating Cuts * (useAltCut, useVertical) = (true, false) => Horizontal Cuts* * (useAltCut, useVertical) = (false, true) => Vertical Cuts * */ void delaunay(Vertex **ppVertices, long numVertices, Edge **ppLe, Edge **ppRe, bool useAltCuts, bool useVertical) { NOT_NULL(ppVertices); if(numVertices == 2) { Edge *pA = Edge::makeEdge(); if(*ppVertices[0] > *ppVertices[1]) { ELEM_SWAP(ppVertices[0], ppVertices[1]); } pA->setOrg(ppVertices[0]); pA->setDest(ppVertices[1]); *ppLe = pA; *ppRe = pA->Sym(); } else if(numVertices == 3) { Edge *pA = Edge::makeEdge(), *pB = Edge::makeEdge(), *pC = 0; if(*ppVertices[0] > *ppVertices[1]) { ELEM_SWAP(ppVertices[0], ppVertices[1]); } if(*ppVertices[1] > *ppVertices[2]) { ELEM_SWAP(ppVertices[1], ppVertices[2]); } Edge::splice(pA->Sym(), pB); pA->setOrg(ppVertices[0]); pA->setDest(ppVertices[1]); pB->setOrg(ppVertices[1]); pB->setDest(ppVertices[2]); REAL ccw = orient2d(ppVertices[0]->Pos(), ppVertices[1]->Pos(), ppVertices[2]->Pos()); if(ccw > 0) { pC = Edge::connect(pB, pA); *ppLe = pA; *ppRe = pB->Sym(); } else if(ccw < 0) { pC = Edge::connect(pB, pA); *ppLe = pC->Sym(); *ppRe = pC; } else { *ppLe = pA; *ppRe = pB->Sym(); } } else { long middle = std::floor(numVertices/2); Edge *pLdo = 0, *pLdi = 0, *pRdi = 0, *pRdo = 0; //These vertices are used for merging a horizontal cut Vertex *pBotMax = 0, //highest vertex of bottom half *pTopMin = 0, //lowest vertex of top half *pMin = 0, //Lexicographically max vertex *pMax = 0; //Lexicographically min vertex //Find median partition by X or Y, depending on whether we're using a vertical cut std::nth_element(ppVertices, ppVertices+middle, ppVertices+numVertices, useVertical ? Vertex::lessX : Vertex::lessY); //Recursive calls delaunay(ppVertices, middle, &pLdo, &pLdi, useAltCuts, useAltCuts ? !useVertical : useVertical); delaunay(ppVertices+middle, numVertices - middle, &pRdi, &pRdo, useAltCuts, useAltCuts ? !useVertical : useVertical); //Modify ldi be highest in bottom half and rdi to be lowest in top half if(!useVertical) { pBotMax = ppVertices[0]; pTopMin = ppVertices[middle]; pMin = (*ppVertices[0] < *ppVertices[middle]) ? ppVertices[0] : ppVertices[middle]; pMax = (*ppVertices[0] > *ppVertices[middle]) ? ppVertices[0] : ppVertices[middle];; for(long i=1; i < middle; i++) { if(*ppVertices[i] < *pMin) { pMin = ppVertices[i]; } else if(*ppVertices[i] > *pMax) { pMax = ppVertices[i]; } if(ppVertices[i]->gtY(*pBotMax)) { pBotMax = ppVertices[i]; } } for(long i=middle+1; i < numVertices; i++) { if(*ppVertices[i] < *pMin) { pMin = ppVertices[i]; } else if(*ppVertices[i] > *pMax) { pMax = ppVertices[i]; } if(ppVertices[i]->ltY(*pTopMin)) { pTopMin = ppVertices[i]; } } pLdi = pBotMax->getCWHullEdge(); pRdi = pTopMin->getCCWHullEdge(); } //Compute the lower common tangent of two sets of vertices while (1) { if(pLdi->leftOf(pRdi->Org())) { pLdi = pLdi->Lnext(); } else if(pRdi->rightOf(pLdi->Org())) { pRdi = pRdi->Rprev(); } else { break; } } // Create a first cross edge pBasel from pRdi.origin to pLdi.origin Edge *pBasel = Edge::connect(pRdi->Sym(), pLdi); if(pLdi->Org() == pLdo->Org()) { pLdo = pBasel->Sym(); } if(pRdi->Org() == pRdo->Org()) { pRdo = pBasel; } //Merging two halves while(1) { //Locate the first Left point pLcand to be encou Edge *pLcand = pBasel->Sym()->Onext(); bool leftFinished = !pLcand->valid(pBasel); if(!leftFinished) { while(incircle(pBasel->Dest()->Pos(), pBasel->Org()->Pos(), pLcand->Dest()->Pos(), pLcand->Onext()->Dest()->Pos()) > 0) { Edge *pT = pLcand->Onext(); Edge::deleteEdge(pLcand); pLcand = pT; } } //Symmetrically locate the first R point to be hit Edge *pRcand = pBasel->Oprev(); bool rightFinished = !pRcand->valid(pBasel); if(!rightFinished) { while(incircle(pBasel->Dest()->Pos(), pBasel->Org()->Pos(), pRcand->Dest()->Pos(), pRcand->Oprev()->Dest()->Pos()) > 0) { Edge *pT = pRcand->Oprev(); Edge::deleteEdge(pRcand); pRcand = pT; } } //both are invalid, pBasel is upper common tangent if(leftFinished && rightFinished) { break; } //the next cross edge is to be connected to either pLcand.dest or pRcand.dest if(leftFinished || (!rightFinished && incircle(pLcand->Dest()->Pos(), pLcand->Org()->Pos(), pRcand->Org()->Pos(), pRcand->Dest()->Pos()) > 0)) { pBasel = Edge::connect(pRcand, pBasel->Sym()); } else { pBasel = Edge::connect(pBasel->Sym(), pLcand->Sym()); } } //Modify pLdo and pRdo if we merging a horizontal cut if(!useVertical) { pLdo = pMin->getCCWHullEdge(); pRdo = pMax->getCWHullEdge(); } *ppLe = pLdo; *ppRe = pRdo; } return; }
int main(int argc, char *argv[]) { SDL_Event ev,az; SDL_Surface *screen; SDL_Surface *kep; SDL_TimerID id; FILE *fp; int x, y,click=0,clicktwo=0,aut=0,quit=0,gomb=0,egerx,egery,nothinghappened=1; cell cells[MAX][MAX]={0}; kep=IMG_Load("sejt.png"); if(!kep) fprintf(stderr, "Nem sikerult betolteni a kepfajlt!\n"); /* SDL inicializálása és ablak megnyitása */ SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); screen=SDL_SetVideoMode(MAX*MERET+KERET*2+100, MAX*MERET+KERET*2-100, 0, SDL_FULLSCREEN); if (!screen) { fprintf(stderr, "Nem sikerult megnyitni az ablakot!\n"); exit(1); } SDL_WM_SetCaption("Game Of Life", "Game Of Life"); SDL_FillRect(screen, NULL, 0x433e3f); boxColor(screen,KERET/3,KERET/3,MAX*MERET+KERET*2-KERET/3,MAX*MERET+KERET*2-KERET/3,KERETSZIN); drawcell(cells,screen,kep); while(!quit) { boxColor(screen, MAX*MERET+KERET*2+10,KERET+5,MAX*MERET+KERET*2+90,KERET+40,0xFFDFD2FF); boxColor(screen, MAX*MERET+KERET*2+14,KERET+9,MAX*MERET+KERET*2+86,KERET+36,0xE5C8BDFF); stringRGBA(screen, MAX*MERET+KERET*2+20, KERET+19, "Leptetes", 255, 255, 255, 255); boxColor(screen, MAX*MERET+KERET*2+10,KERET+5+HEZAG,MAX*MERET+KERET*2+90,KERET+40+HEZAG,0xFFDFD2FF); boxColor(screen, MAX*MERET+KERET*2+14,KERET+9+HEZAG,MAX*MERET+KERET*2+86,KERET+36+HEZAG,0xE5C8BDFF); if(aut==0) stringRGBA(screen, MAX*MERET+KERET*2+15, KERET+69, "Szimul.be", 255, 255, 255, 255); else stringRGBA(screen, MAX*MERET+KERET*2+15, KERET+69, "Szimul.ki", 255, 255, 255, 255); boxColor(screen, MAX*MERET+KERET*2+10,KERET+5+HEZAG*2,MAX*MERET+KERET*2+90,KERET+40+HEZAG*2,0xFFDFD2FF); boxColor(screen, MAX*MERET+KERET*2+14,KERET+9+HEZAG*2,MAX*MERET+KERET*2+86,KERET+36+HEZAG*2,0xE5C8BDFF); stringRGBA(screen, MAX*MERET+KERET*2+26, KERET+19+HEZAG*2, "Torles", 255, 255, 255, 255); boxColor(screen, MAX*MERET+KERET*2+10,KERET+5+HEZAG*3,MAX*MERET+KERET*2+90,KERET+40+HEZAG*3,0xFFDFD2FF); boxColor(screen, MAX*MERET+KERET*2+14,KERET+9+HEZAG*3,MAX*MERET+KERET*2+86,KERET+36+HEZAG*3,0xE5C8BDFF); stringRGBA(screen, MAX*MERET+KERET*2+27, KERET+19+HEZAG*3, "Kilovo", 255, 255, 255, 255); filledCircleColor(screen,MAX*MERET+2*KERET+80,9,8,0xFFDFD2FF); filledCircleColor(screen,MAX*MERET+2*KERET+80,9,6,0xE5C8BDFF); stringRGBA(screen,MAX*MERET+KERET*2+77,6,"X",255,255,255,255); SDL_Flip(screen); while(SDL_PollEvent(&ev)){ switch(ev.type) { /*case SDL_KEYDOWN: switch(ev.key.keysym.sym) { case SDLK_s: mentes(cells); break; case SDLK_l: fp=fopen("save.txt","r"); for(y=0;y<MAX;y++) for(x=0;x<MAX;x++) fscanf(fp,"%d ",&cells[y][x].alive); fclose (fp); drawcell(cells,screen,kep); SDL_Flip(screen); break; } break;*/ case SDL_MOUSEBUTTONDOWN: if(ev.button.button==SDL_BUTTON_LEFT) { if(ev.button.x<=MAX*MERET+KERET){ egerx=holazeger(ev.button.x); egery=holazeger(ev.button.y); if(cells[egery][egerx].alive==1) cells[egery][egerx].alive=0; else cells[egery][egerx].alive=1; } else if(incircle(ev.button.x,ev.button.y,MAX*MERET+2*KERET+80,9,8)) quit=1; else if((ev.button.x<=MAX*MERET+KERET*2+90 && ev.button.x>=MAX*MERET+KERET*2+10) && (ev.button.y<=KERET+40 && ev.button.y>=KERET+5))//egyes lépés { round(cells); } else if((ev.button.x<=MAX*MERET+KERET*2+90 && ev.button.x>=MAX*MERET+KERET*2+10) && (ev.button.y<=KERET+90 && ev.button.y>=KERET+55))//szimulálás { if(aut==0) aut=1; else aut=0; } else if((ev.button.x<=MAX*MERET+KERET*2+90 && ev.button.x>=MAX*MERET+KERET*2+10) && (ev.button.y<=KERET+40+HEZAG*2 && ev.button.y>=KERET+5+HEZAG*2))//egyes lépés { for(y=0;y<MAX;y++) for(x=0;x<MAX;x++) cells[y][x].alive=0; } else if((ev.button.x<=MAX*MERET+KERET*2+90 && ev.button.x>=MAX*MERET+KERET*2+10) && (ev.button.y<=KERET+40+HEZAG*3 && ev.button.y>=KERET+5+HEZAG*3))//egyes lépés { fp=fopen("save.txt","r"); for(y=0;y<MAX;y++) for(x=0;x<MAX;x++) fscanf(fp,"%d ",&cells[y][x].alive); fclose (fp); drawcell(cells,screen,kep); SDL_Flip(screen); } drawcell(cells,screen,kep); SDL_Flip(screen); } break; case SDL_MOUSEBUTTONUP: if(ev.button.button==SDL_BUTTON_LEFT) { click=0; clicktwo=0; } break; case SDL_QUIT: quit=1; break; } } if(aut) { SDL_Delay(100); round(cells); drawcell(cells,screen,kep); SDL_Flip(screen); } } SDL_FreeSurface(kep); SDL_Quit(); exit(0); return 0; }
static void rec_delaunay(site_struct * sites[], int sl, int sh, edge_ref * le, edge_ref * re) { if (sh == sl + 2) { edge_ref a = make_edge(); ODATA(a) = sites[sl]; DDATA(a) = sites[sl + 1]; *le = a; *re = SYM(a); } else if (sh == sl + 3) { edge_ref a = make_edge(); edge_ref b = make_edge(); double ct = ccw(sites[sl], sites[sl + 1], sites[sl + 2]); splice(SYM(a), b); ODATA(a) = sites[sl]; DDATA(a) = sites[sl + 1]; ODATA(b) = sites[sl + 1]; DDATA(b) = sites[sl + 2]; if (ct == 0.0) { *le = a; *re = SYM(b); } else { edge_ref c = connect(b, a); if (ct > 0.0) { *le = a; *re = SYM(b); } else { *le = SYM(c); *re = c; } } } else { edge_ref ldo, ldi, rdi, rdo; edge_ref basel, lcand, rcand; int sm = (sl + sh) / 2; rec_delaunay(sites, sl, sm, &ldo, &ldi); rec_delaunay(sites, sm, sh, &rdi, &rdo); while (1) { if (leftof(ORG(rdi), ldi)) ldi = LNEXT(ldi); else if (rightof(ORG(ldi), rdi)) rdi = ONEXT(SYM(rdi)); else break; } basel = connect(SYM(rdi), ldi); if (ORG(ldi) == ORG(ldo)) ldo = SYM(basel); if (ORG(rdi) == ORG(rdo)) rdo = basel; while (1) { lcand = ONEXT(SYM(basel)); if (rightof(DEST(lcand), basel)) while (incircle (DEST(basel), ORG(basel), DEST(lcand), DEST(ONEXT(lcand)))) { edge_ref t = ONEXT(lcand); destroy_edge(lcand); lcand = t; } rcand = OPREV(basel); if (rightof(DEST(rcand), basel)) while (incircle (DEST(basel), ORG(basel), DEST(rcand), DEST(OPREV(rcand)))) { edge_ref t = OPREV(rcand); destroy_edge(rcand); rcand = t; } if (!rightof(DEST(lcand), basel) && !rightof(DEST(rcand), basel)) break; if (!rightof(DEST(lcand), basel) || (rightof(DEST(rcand), basel) && incircle(DEST(lcand), ORG(lcand), ORG(rcand), DEST(rcand)))) basel = connect(rcand, SYM(basel)); else basel = connect(SYM(basel), SYM(lcand)); } *le = ldo; *re = rdo; } }