Point min_center() { o = p[0]; r = 0; for(int i=1; i<n; i++)//准备加入的点 { if(dis(p[i], o)-r > eps)//如果第i点在 i-1前最小圆外面 { o = p[i];//另定圆心 r = 0;//另定半径 for(int j=0; j<i; j++)//循环再确定半径 { if(dis(p[j], o)-r > eps) { o.x = (p[i].x + p[j].x) / 2.0; o.y = (p[i].y + p[j].y) / 2.0; r = dis( o, p[j]); for(int k = 0; k<j; k++) { if(dis(o, p[k])-r > eps)//如果j前面有点不符和 i与j确定的圆,则更新 { o = circumcenter(p[i], p[j], p[k]); r = dis(o, p[k]); } }//循环不超过3层,因为一个圆最多3个点可以确定 } } } } return o; }
double circumradius(const Facet& f) { Point c = circumcenter(f); Point p = f.first->vertex((f.second+1)%4)->point(); return sqrt(CGAL::to_double((p-c)*(p-c))); }
circle spanning_circle(vector<point>& T) { int n = T.size(); random_shuffle(ALL(T)); circle C(point(), -INFINITY); for (int i = 0; i < n; i++) if (!in_circle(C, T[i])) { C = circle(T[i], 0); for (int j = 0; j < i; j++) if (!in_circle(C, T[j])) { C = circle((T[i] + T[j]) / 2, abs(T[i] - T[j]) / 2); for (int k = 0; k < j; k++) if (!in_circle(C, T[k])) { point o = circumcenter(T[i], T[j], T[k]); C = circle(o, abs(o - T[k])); } } } return C; }
int main() { point a,b,c; point center; double r; while (scanf("%lf %lf %lf %lf %lf %lf",&a.x,&a.y,&b.x,&b.y,&c.x,&c.y) != EOF) { center = circumcenter(a,b,c); r = distance(center,a); printf("%.2lf\n",2*PI*r); } return 0; }
circle enclosing_circle(vector<pt>& pts){ srand(unsigned(time(0))); random_shuffle(pts.begin(), pts.end()); circle c(pt(), -1); for (int i = 0; i < pts.size(); ++i){ if (point_circle(pts[i], c)) continue; c = circle(pts[i], 0); for (int j = 0; j < i; ++j){ if (point_circle(pts[j], c)) continue; c = circle((pts[i] + pts[j])/2, abs(pts[i] - pts[j])/2); for (int k = 0; k < j; ++k){ if (point_circle(pts[k], c)) continue; pt center = circumcenter(pts[i], pts[j], pts[k]); c = circle(center, abs(center - pts[i])/2); } } } return c; }
void Foam::CV2D::calcDual ( point2DField& dualPoints, faceList& dualFaces, wordList& patchNames, labelList& patchSizes, EdgeMap<label>& mapEdgesRegion, EdgeMap<label>& indirectPatchEdge ) const { // Dual points stored in triangle order. dualPoints.setSize(number_of_faces()); label dualVerti = 0; for ( Triangulation::Finite_faces_iterator fit = finite_faces_begin(); fit != finite_faces_end(); ++fit ) { if ( fit->vertex(0)->internalOrBoundaryPoint() || fit->vertex(1)->internalOrBoundaryPoint() || fit->vertex(2)->internalOrBoundaryPoint() ) { fit->faceIndex() = dualVerti; dualPoints[dualVerti++] = toPoint2D(circumcenter(fit)); } else { fit->faceIndex() = -1; } } dualPoints.setSize(dualVerti); extractPatches(patchNames, patchSizes, mapEdgesRegion, indirectPatchEdge); forAll(patchNames, patchi) { Info<< "Patch " << patchNames[patchi] << " has size " << patchSizes[patchi] << endl; } // Create dual faces // ~~~~~~~~~~~~~~~~~ dualFaces.setSize(number_of_vertices()); label dualFacei = 0; labelList faceVerts(maxNvert); for ( Triangulation::Finite_vertices_iterator vit = finite_vertices_begin(); vit != finite_vertices_end(); ++vit ) { if (vit->internalOrBoundaryPoint()) { Face_circulator fcStart = incident_faces(vit); Face_circulator fc = fcStart; label verti = 0; do { if (!is_infinite(fc)) { if (fc->faceIndex() < 0) { FatalErrorInFunction << "Dual face uses vertex defined by a triangle" " defined by an external point" << exit(FatalError); } // Look up the index of the triangle faceVerts[verti++] = fc->faceIndex(); } } while (++fc != fcStart); if (faceVerts.size() > 2) { dualFaces[dualFacei++] = face(labelList::subList(faceVerts, verti)); } else { Info<< "From triangle point:" << vit->index() << " coord:" << toPoint2D(vit->point()) << " generated illegal dualFace:" << faceVerts << endl; } } } dualFaces.setSize(dualFacei); }
void Foam::CV2D::writeFaces(const fileName& fName, bool internalOnly) const { Info<< "Writing dual faces to " << fName << nl << endl; OFstream str(fName); label dualVerti = 0; for ( Triangulation::Finite_faces_iterator fit = finite_faces_begin(); fit != finite_faces_end(); ++fit ) { if ( !internalOnly || ( fit->vertex(0)->internalOrBoundaryPoint() || fit->vertex(1)->internalOrBoundaryPoint() || fit->vertex(2)->internalOrBoundaryPoint() ) ) { fit->faceIndex() = dualVerti++; meshTools::writeOBJ(str, toPoint3D(circumcenter(fit))); } else { fit->faceIndex() = -1; } } for ( Triangulation::Finite_vertices_iterator vit = finite_vertices_begin(); vit != finite_vertices_end(); ++vit ) { if (!internalOnly || vit->internalOrBoundaryPoint()) { Face_circulator fcStart = incident_faces(vit); Face_circulator fc = fcStart; str<< 'f'; do { if (!is_infinite(fc)) { if (fc->faceIndex() < 0) { FatalErrorInFunction << "Dual face uses vertex defined by a triangle" " defined by an external point" << exit(FatalError); } str<< ' ' << fc->faceIndex() + 1; } } while (++fc != fcStart); str<< nl; } } }
void Graph::create(const vector< vector<Cell_handle> >& chains, const vector<COMPUTATION_STATUS>& chains_property, const vector< Facet >& start_of_chains) { // `chains' is a collection of chains each of which is given by a list // of ordered vertices on it. the edges are therefore implicitly defined // between two consecutive vertices in the list. It has impurity because // some edges are not correct. So, we collect only the correct edges // and remove any duplication. We call it pure_chains. vector< vector<int> > pure_chains; pure_chains.resize((int)chains.size()); int current_pure_chain = -1; // we first create a set of vertices. we omit duplication at the start // and end of chains by consulting the vector start_end_of_chains. for(int i = 0; i < (int)chains.size(); i ++) { if(chains_property[i] != SUCCESS) continue; if((int)chains[i].size() == 0) continue; current_pure_chain++; Facet i2f = start_of_chains[i]; if( i2f.first->saddle_g_vid[i2f.second] == -1) { vert_list.push_back( GVertex(circumcenter(start_of_chains[i])) ); vert_list[(int)vert_list.size()-1].id = (int)vert_list.size()-1; vert_list[(int)vert_list.size()-1].c = i2f.first; pure_chains[current_pure_chain].push_back((int)vert_list.size()-1); Cell_handle c[2]; int id[2]; c[0] = i2f.first; id[0] = i2f.second; c[1] = c[0]->neighbor(id[0]); id[1] = c[1]->index(c[0]); c[0]->saddle_g_vid[id[0]] = (int)vert_list.size()-1; c[1]->saddle_g_vid[id[1]] = (int)vert_list.size()-1; vert_list[(int)vert_list.size()-1].set_out(c[0]->outside && c[1]->outside ); // if either of the three VFs incident on the VE (dual to Face(c[0], id[0])) // is on_um_i1, this graph vertex is also on um_i1. int u = (id[0]+1)%4, v = (id[0]+2)%4, w = (id[0]+3)%4; if(c[0]->VF_on_um_i1(u,v) || c[0]->VF_on_um_i1(v,w) || c[0]->VF_on_um_i1(w,u) ) vert_list[(int)vert_list.size()-1].set_on_um_i1(true); // collect the clusters the incident VFs fall into. if(c[0]->patch_id[u][v] != -1) vert_list[(int)vert_list.size()-1].cluster_membership.push_back(c[0]->patch_id[u][v]); if(c[0]->patch_id[v][w] != -1 && c[0]->patch_id[v][w] != c[0]->patch_id[u][v]) vert_list[(int)vert_list.size()-1].cluster_membership.push_back(c[0]->patch_id[v][w]); if(c[0]->patch_id[w][u] != -1 && c[0]->patch_id[w][u] != c[0]->patch_id[u][v] && c[0]->patch_id[w][u] != c[0]->patch_id[v][w] ) vert_list[(int)vert_list.size()-1].cluster_membership.push_back(c[0]->patch_id[w][u]); if((int)vert_list[(int)vert_list.size()-1].cluster_membership.size() >= 2) cerr << " >= 2 "; } else { pure_chains[current_pure_chain].push_back(i2f.first->saddle_g_vid[i2f.second]); } for(int j = 0; j < (int)chains[i].size(); j ++) { // if the cell is already included by another chain if(chains[i][j]->g_vid != -1) pure_chains[current_pure_chain].push_back(chains[i][j]->g_vid); else // add its voronoi as a vertex in the graph { vert_list.push_back(GVertex(chains[i][j]->voronoi())); vert_list[(int)vert_list.size()-1].id = (int)vert_list.size()-1; vert_list[(int)vert_list.size()-1].c = chains[i][j]; pure_chains[current_pure_chain].push_back((int)vert_list.size()-1); chains[i][j]->g_vid = (int)vert_list.size()-1; vert_list[(int)vert_list.size()-1].set_out(chains[i][j]->outside); // keep the info if this cell also lies on um(i1). if(chains[i][j]->VV_on_um_i1()) { vert_list[(int)vert_list.size()-1].set_on_um_i1(true); for(int u = 0; u < 4; u ++) { for(int v = u+1; v < 4; v ++) { if(chains[i][j]->patch_id[u][v] == -1) continue; bool found = false; for(int k = 0; k < (int)vert_list[(int)vert_list.size()-1].cluster_membership.size(); k ++) if(vert_list[(int)vert_list.size()-1].cluster_membership[k] == chains[i][j]->patch_id[u][v]) found = true; if(found) continue; vert_list[(int)vert_list.size()-1].cluster_membership.push_back( chains[i][j]->patch_id[u][v]); } } } } } } set_nv((int)vert_list.size()); for(int i = 0; i < (int)pure_chains.size(); i ++) { if((int)pure_chains[i].size() == 0) continue; for(int j = 0; j < (int)pure_chains[i].size() - 1; j ++) { edge_list.push_back(GEdge(pure_chains[i][j], pure_chains[i][j+1])); edge_list[(int)edge_list.size()-1].id = (int)edge_list.size()-1; // we have considered only the chains with status == SUCCESS. edge_list[(int)edge_list.size()-1].set_status(SUCCESS); // update adjacency information. // vertex vert_list[pure_chains[i][j]].add_inc_vert(pure_chains[i][j+1]); vert_list[pure_chains[i][j+1]].add_inc_vert(pure_chains[i][j]); // edge vert_list[pure_chains[i][j]].add_inc_edge((int)edge_list.size()-1); vert_list[pure_chains[i][j+1]].add_inc_edge((int)edge_list.size()-1); } } set_ne((int)edge_list.size()); }
Point orthocenter(const Point &a, const Point &b, const Point &c) { return a + b + c - circumcenter(a, b, c) * 2.0; }
void Foam::CV2D::newPoints() { const scalar relaxation = relaxationModel_->relaxation(); Info<< "Relaxation = " << relaxation << endl; Field<point2D> dualVertices(number_of_faces()); label dualVerti = 0; // Find the dual point of each tetrahedron and assign it an index. for ( Triangulation::Finite_faces_iterator fit = finite_faces_begin(); fit != finite_faces_end(); ++fit ) { fit->faceIndex() = -1; if ( fit->vertex(0)->internalOrBoundaryPoint() || fit->vertex(1)->internalOrBoundaryPoint() || fit->vertex(2)->internalOrBoundaryPoint() ) { fit->faceIndex() = dualVerti; dualVertices[dualVerti] = toPoint2D(circumcenter(fit)); dualVerti++; } } dualVertices.setSize(dualVerti); Field<vector2D> displacementAccumulator ( startOfSurfacePointPairs_, vector2D::zero ); // Calculate target size and alignment for vertices scalarField sizes ( number_of_vertices(), meshControls().minCellSize() ); Field<vector2D> alignments ( number_of_vertices(), vector2D(1, 0) ); for ( Triangulation::Finite_vertices_iterator vit = finite_vertices_begin(); vit != finite_vertices_end(); ++vit ) { if (vit->internalOrBoundaryPoint()) { point2D vert = toPoint2D(vit->point()); // alignment and size determination pointIndexHit pHit; label hitSurface = -1; qSurf_.findSurfaceNearest ( toPoint3D(vert), meshControls().span2(), pHit, hitSurface ); if (pHit.hit()) { vectorField norm(1); allGeometry_[hitSurface].getNormal ( List<pointIndexHit>(1, pHit), norm ); alignments[vit->index()] = toPoint2D(norm[0]); sizes[vit->index()] = cellSizeControl_.cellSize ( toPoint3D(vit->point()) ); } } } // Info<< "Calculated alignments" << endl; scalar cosAlignmentAcceptanceAngle = 0.68; // Upper and lower edge length ratios for weight scalar u = 1.0; scalar l = 0.7; PackedBoolList pointToBeRetained(startOfSurfacePointPairs_, true); std::list<Point> pointsToInsert; for ( Triangulation::Finite_edges_iterator eit = finite_edges_begin(); eit != finite_edges_end(); eit++ ) { Vertex_handle vA = eit->first->vertex(cw(eit->second)); Vertex_handle vB = eit->first->vertex(ccw(eit->second)); if (!vA->internalOrBoundaryPoint() || !vB->internalOrBoundaryPoint()) { continue; } const point2D& dualV1 = dualVertices[eit->first->faceIndex()]; const point2D& dualV2 = dualVertices[eit->first->neighbor(eit->second)->faceIndex()]; scalar dualEdgeLength = mag(dualV1 - dualV2); point2D dVA = toPoint2D(vA->point()); point2D dVB = toPoint2D(vB->point()); Field<vector2D> alignmentDirsA(2); alignmentDirsA[0] = alignments[vA->index()]; alignmentDirsA[1] = vector2D ( -alignmentDirsA[0].y(), alignmentDirsA[0].x() ); Field<vector2D> alignmentDirsB(2); alignmentDirsB[0] = alignments[vB->index()]; alignmentDirsB[1] = vector2D ( -alignmentDirsB[0].y(), alignmentDirsB[0].x() ); Field<vector2D> alignmentDirs(alignmentDirsA); forAll(alignmentDirsA, aA) { const vector2D& a(alignmentDirsA[aA]); scalar maxDotProduct = 0.0; forAll(alignmentDirsB, aB) { const vector2D& b(alignmentDirsB[aB]); scalar dotProduct = a & b; if (mag(dotProduct) > maxDotProduct) { maxDotProduct = mag(dotProduct); alignmentDirs[aA] = a + sign(dotProduct)*b; alignmentDirs[aA] /= mag(alignmentDirs[aA]); } } } vector2D rAB = dVA - dVB; scalar rABMag = mag(rAB); forAll(alignmentDirs, aD) { vector2D& alignmentDir = alignmentDirs[aD]; if ((rAB & alignmentDir) < 0) { // swap the direction of the alignment so that has the // same sense as rAB alignmentDir *= -1; } scalar alignmentDotProd = ((rAB/rABMag) & alignmentDir); if (alignmentDotProd > cosAlignmentAcceptanceAngle) { scalar targetFaceSize = 0.5*(sizes[vA->index()] + sizes[vB->index()]); // Test for changing aspect ratio on second alignment (first // alignment is neartest surface normal) // if (aD == 1) // { // targetFaceSize *= 2.0; // } alignmentDir *= 0.5*targetFaceSize; vector2D delta = alignmentDir - 0.5*rAB; if (dualEdgeLength < 0.7*targetFaceSize) { delta *= 0; } else if (dualEdgeLength < targetFaceSize) { delta *= ( dualEdgeLength /(targetFaceSize*(u - l)) - 1/((u/l) - 1) ); } if ( vA->internalPoint() && vB->internalPoint() && rABMag > 1.75*targetFaceSize && dualEdgeLength > 0.05*targetFaceSize && alignmentDotProd > 0.93 ) { // Point insertion pointsToInsert.push_back(toPoint(0.5*(dVA + dVB))); } else if ( (vA->internalPoint() || vB->internalPoint()) && rABMag < 0.65*targetFaceSize ) { // Point removal // Only insert a point at the midpoint of the short edge // if neither attached point has already been identified // to be removed. if ( pointToBeRetained[vA->index()] == true && pointToBeRetained[vB->index()] == true ) { pointsToInsert.push_back(toPoint(0.5*(dVA + dVB))); } if (vA->internalPoint()) { pointToBeRetained[vA->index()] = false; } if (vB->internalPoint()) { pointToBeRetained[vB->index()] = false; } } else { if (vA->internalPoint()) { displacementAccumulator[vA->index()] += delta; } if (vB->internalPoint()) { displacementAccumulator[vB->index()] += -delta; } } } } }
void BMMap::make_edges_delauney( ) { for (int i=0; i < nloc; i++) { for (int j=0; j < nloc; j++) { adj[i][j].pass = 0; } } // DBG: fill in edges at random #if 0 for (i=0; i <10; i++) { int l1,l2; l1 = random( nloc ); l2 = random( nloc ); adj[l1][l2].pass = 1; adj[l2][l1].pass = 1; } #endif std::vector<Triangle> tris, tris2; tris.push_back( Triangle() ); tris.push_back( Triangle() ); tris[0].ax = 0; tris[0].ay = 0; tris[0].bx = 800; tris[0].by = 0; tris[0].cx = 800; tris[0].cy = 600; tris[1].ax = 0; tris[1].ay = 0; tris[1].bx = 0; tris[1].by = 600; tris[1].cx = 800; tris[1].cy = 600; // edgelist std::vector<Edge> edge; for (int ndx=0; ndx < nloc; ndx++) { // init lists tris2.erase( tris2.begin(), tris2.end() ); edge.erase( edge.begin(), edge.end() ); // find all triangle whose circumcenter contains loc ndx for (i=0; i < tris.size(); i++) { float cx, cy, rad; circumcenter( tris[i], cx, cy, rad ); float d = sqrt( (loc[ndx].xpos - cx) * (loc[ndx].xpos - cx) + (loc[ndx].ypos - cy) * (loc[ndx].ypos - cy) ); if (d <= rad) { // in triangle circumcenter, add to edgelist add_edge( edge, tris[i].ax, tris[i].ay, tris[i].bx, tris[i].by ); add_edge( edge, tris[i].bx, tris[i].by, tris[i].cx, tris[i].cy ); add_edge( edge, tris[i].cx, tris[i].cy, tris[i].ax, tris[i].ay ); } else { // just keep the tri tris2.push_back( tris[i] ); //printf("Keeping tri %i\n", i ); } } // add a triangle for every edge appearing once in the list for (i=0; i < edge.size(); i++) { if ( edge[i].count == 1 ) { Triangle t; t.ax = loc[ndx].xpos; t.ay = loc[ndx].ypos; t.bx = edge[i].x1; t.by = edge[i].y1; t.cx = edge[i].x2; t.cy = edge[i].y2; tris2.push_back( t ); //printf("constructing tri\n" ); } } // update the list tris = tris2; } // convert the tris to adjacency for (i=0; i < tris.size(); i++) { int andx, bndx, cndx; andx = -1; bndx = -1; cndx = -1; for (int j=0; j < nloc; j++) { if ( ((int)tris[i].ax == loc[j].xpos) && ((int)tris[i].ay == loc[j].ypos) ) andx = j; if ( ((int)tris[i].bx == loc[j].xpos) && ((int)tris[i].by == loc[j].ypos) ) bndx = j; if ( ((int)tris[i].cx == loc[j].xpos) && ((int)tris[i].cy == loc[j].ypos) ) cndx = j; } if ( (andx > 0) && (bndx >=0 )) { adj[andx][bndx].pass = 1; adj[bndx][andx].pass = 1; if (!adj[andx][bndx].de) { DualEdge *de = find_dual_edge( tris, andx, bndx ); adj[andx][bndx].de = de; adj[bndx][andx].de = de; } } if ( (bndx > 0) && (cndx >=0 )) { adj[bndx][cndx].pass = 1; adj[cndx][bndx].pass = 1; if (!adj[bndx][cndx].de) { DualEdge *de = find_dual_edge( tris, bndx, cndx ); adj[bndx][cndx].de = de; adj[cndx][bndx].de = de; } } if ( (cndx > 0) && (andx >=0 )) { adj[cndx][andx].pass = 1; adj[andx][cndx].pass = 1; if (!adj[cndx][andx].de) { DualEdge *de = find_dual_edge( tris, cndx, andx ); adj[cndx][andx].de = de; adj[andx][cndx].de = de; } } } }
Circle(const Point &a, const Point &c, const Point &d): o(circumcenter(a, b, c)) { r = ((a - o).norm() + (b - o).norm() + (c - o).norm()) / 3.0; }