File:Poincare halfplane heptagonal hb.svg
页面内容不支持其他语言。
外观
此SVG文件的PNG预览的大小:800 × 400像素。 其他分辨率:320 × 160像素 | 640 × 320像素 | 1,024 × 512像素 | 1,280 × 640像素 | 2,560 × 1,280像素。
原始文件 (SVG文件,尺寸为800 × 400像素,文件大小:173 KB)
摘要
描述Poincare halfplane heptagonal hb.svg | Stellated Eptagonal honeycomb (tiling) of the Poincare Half-Plane Model |
日期 | |
来源 | 自己的作品 |
作者 | Claudio Rocchini |
授权 (二次使用本文件) |
CC-BY 3.0 |
Source Code
The complete and dirty C++ generating source code:
/* Poincare Half-plane model (C)2007 Claudio Rocchini, the SHQN man */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <assert.h> #include <vector> const double PI = 3.1415926535897932384626433832795; const double EPS = 1e-12; const double EPS2 = 1e-4; const int dimx = 800; const int dimy = 400; const int OX = dimx/2; const int OY = dimy; namespace hp { class point { public: double x,y; point(){} point( double nx, double ny ) : x(nx),y(ny) {} }; class line { protected: void at_param( double t, point & q ) const; double param( const point & q ) const; public: bool di; // direzione: diretta o rovesciata double ra; // raggio: 0 = linea verticale double cx; // centro vertice void from_points( const point & p, const point & q ); void from_point_angle( const point & p, double a ); void at_dist( const point & p, double d, bool dir, point & q ) const; double angle( const point & p ) const; }; double dist( const point & p, const point & q ); void line::from_points( const point & p, const point & q ) { if( fabs(p.x-q.x)<EPS ) { ra = 0; cx = 0.5*(p.x+q.x); } else { cx = 0.5*(q.x*q.x+q.y*q.y-p.x*p.x-p.y*p.y)/(q.x-p.x); ra = sqrt( (p.x-cx)*(p.x-cx)+p.y*p.y ); } double ip = param(p); double iq = param(q); di = ip<iq; } void line::from_point_angle( const point & p, double a ){ if( fabs(a-PI/2)<EPS || fabs(a-PI*3/2)<EPS ) { ra = 0; cx = p.x; } else { double b = a+PI/2; double co = cos(b); double si = sin(b); ra = fabs(p.y/si); cx = -(p.y*co-p.x*si)/si; } di = cos(a)>=0; } void line::at_param( double t, point & q ) const { if(ra==0) { q.x = cx; q.y = t; } else { q.x = ra*cos(t) + cx; q.y = ra*sin(t); } } double line::param( const point & q ) const { if(ra==0) return q.y; else return atan2(q.y,q.x-cx); } void line::at_dist( const point & p, double d, bool dir, point & q ) const { if(ra==0) { double tmi,tma,tmm; if(dir!=di) { tmi = 0 + EPS; tma = param(p); for(;;) { tmm = (tmi+tma)/2; at_param(tmm,q); double ld = dist(p,q); if(ld>d) tmi = tmm; else tma = tmm; if(tma-tmi<EPS) break; } } else { tmi = param(p); tma = tmi*100; for(;;) { tmm = (tmi+tma)/2; at_param(tmm,q); double ld = dist(p,q); if(ld<d) tmi = tmm; else tma = tmm; if(tma-tmi<EPS) break; } } } else { double tmi,tma,tmm; if(dir!=di) { tmi = 0 + EPS; tma = param(p); for(;;) { tmm = (tmi+tma)/2; at_param(tmm,q); double ld = dist(p,q); if(ld>d) tmi = tmm; else tma = tmm; if(tma-tmi<EPS) break; } } else { tmi = param(p); tma = PI-EPS; for(;;) { tmm = (tmi+tma)/2; at_param(tmm,q); double ld = dist(p,q); if(ld<d) tmi = tmm; else tma = tmm; if(tma-tmi<EPS) break; } } } } double line::angle( const point & p ) const { double a = 0; if(ra==0) a = PI/2; else a = atan2(p.y,p.x-cx) - PI/2; if(di) a += PI; return a; } double dist( const point & p, const point & q ) { line l; l.from_points(p,q); if(l.ra!=0) { double A = l.cx - l.ra; double B = l.cx + l.ra; double PA = sqrt( (p.x-A)*(p.x-A)+p.y*p.y ); double PB = sqrt( (p.x-B)*(p.x-B)+p.y*p.y ); double QA = sqrt( (q.x-A)*(q.x-A)+q.y*q.y ); double QB = sqrt( (q.x-B)*(q.x-B)+q.y*q.y ); return fabs(log( (PA/PB) / (QA/QB) )); } else { double A = l.cx; double PA = sqrt( (p.x-A)*(p.x-A)+p.y*p.y ); double QA = sqrt( (q.x-A)*(q.x-A)+q.y*q.y ); return fabs(log( (PA/QA) )); } } void draw_point( FILE * fp, const point & p, double R ) { fprintf(fp,"<circle cx=\"%5.1lf\" cy=\"%5.1lf\" r=\"%g\"/>\n",p.x+OX,OY-p.y,R); } void draw_line( FILE * fp, const line & l ) { if(l.ra==0) fprintf(fp,"<line x1=\"%5.1lf\" y1=\"0\" x2=\"%5.1lf\" y2=\"%5.1lf\"/>" ,OX+l.cx ,OX+l.cx ,double(dimy) ); else fprintf(fp,"<path d=\"M %5.1lf,%5.1lf A %g,%g 0 0,1 %5.1lf,%5.1lf\"/>\n" ,OX+l.cx-l.ra,double(dimy),l.ra,l.ra,OX+l.cx+l.ra,double(dimy) ); } void draw_arc( FILE * fp, const line & l, const point & p, const point & q ) { if(l.ra==0) fprintf(fp,"<line x1=\"%5.1lf\" y1=\"%5.1lf\" x2=\"%5.1lf\" y2=\"%5.1lf\"/>\n" ,OX+l.cx,OY-p.y,OX+l.cx,OY-q.y); else fprintf(fp,"<path d=\"M %5.1lf,%5.1lf A %g,%g 0 0,%d %5.1lf,%5.1lf\"/>\n" ,OX+p.x,OY-p.y,l.ra,l.ra,p.x<q.x ? 1 : 0,OX+q.x,OY-q.y); } double e_dist( const point & p1, const point & p2 ){ const double dx = p1.x - p2.x; const double dy = p1.y - p2.y; return sqrt(dx*dx+dy*dy); } } // End namespace hp class edge { public: int i[2]; edge(){} edge( int i0, int i1 ) { i[0]=i0; i[1]=i1; } inline operator== ( const edge & e ) const { return (i[0]==e.i[0] && i[1]==e.i[1]) || (i[0]==e.i[1] && i[1]==e.i[0]) ; } }; int main(){ const double R = 2; const int L = 7; const double qangle = 2*PI/3; // Angolo di tassellazione std::vector<hp::point> nodes; std::vector< edge > edges; std::vector< edge > edges2; int i; // Ricerca lato hp::point q[L]; hp::point c(dimx/2-502.5,dimy/2); const double sangle = 0; double lato = 0; double milato = 1e-4; double malato = 5; const int D = 2; for(;;) { lato = (milato+malato)/2; q[0] = c; hp::line k; k.from_point_angle(c,sangle); k.at_dist(c,lato,false,q[1]); for(i=1;i<L-1;++i) { hp::line l; l.from_points(q[i-1],q[i]); double a0 = l.angle(q[i]); a0 -= PI-qangle; hp::line l1; l1.from_point_angle(q[i],a0); l1.at_dist(q[i],lato,false,q[i+1]); } double d = hp::dist(q[0],q[L-1]); if(d<lato) milato = lato; else malato = lato; if( malato-milato<EPS) { lato = (milato+malato)/2; break; } } std::vector< int > openedges; q[0] = c; hp::line k; k.from_point_angle(c,sangle); k.at_dist(c,lato,false,q[1]); for(i=1;i<L-1;++i) { hp::line l; l.from_points(q[i-1],q[i]); double a0 = l.angle(q[i]); a0 -= PI-qangle; hp::line l1; l1.from_point_angle(q[i],a0); l1.at_dist(q[i],lato,false,q[i+1]); } for(i=0;i<L;++i) { nodes.push_back(q[i]); edges.push_back( edge(i,(i+1)%L) ); openedges.push_back( edges.size()-1 ); } for(i=0;i<L;++i) edges2.push_back( edge(i,(i+D)%L) ); // Ciclo di espansione int nn = 0; int maxn = 3000; while( !openedges.empty() ) { int e = openedges.front(); //openedges.erase( openedges.begin() ); int ip1 = edges[e].i[0]; int ip0 = edges[e].i[1]; hp::point p0 = nodes[ ip0 ]; hp::point p1 = nodes[ ip1 ]; int eee[L]; for(i=0;i<L;++i) { eee[i] = ip0; hp::line l; l.from_points(p0,p1); double a0 = l.angle(p1); a0 -= PI-qangle; hp::line l1; l1.from_point_angle(p1,a0); hp::point p2; l1.at_dist(p1,lato,false,p2); int ip2 = -1; for(ip2=0;ip2<nodes.size();++ip2) if( hp::e_dist(nodes[ip2],p2)<EPS2 ) break; if(ip2==nodes.size()) nodes.push_back(p2); edge e(ip1,ip2); std::vector< int >::iterator jj; for(jj=openedges.begin();jj!=openedges.end();++jj) if(edges[*jj]==e) break; if(jj==openedges.end()) { openedges.push_back(edges.size()); edges.push_back(e); } else openedges.erase(jj); p0 = p1; ip0 = ip1; p1 = p2; ip1 = ip2; } for(i=0;i<L;++i) edges2.push_back( edge(eee[i],eee[(i+D)%L]) ); if(++nn>=maxn) break; } FILE * fp = fopen("hp.svg","w"); fprintf(fp, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" "<!-- Created with svg-rocco-library v1.0 -->\n" "<svg\n" "xmlns:svg=\"http://www.w3.org/2000/svg\"\n" "xmlns=\"http://www.w3.org/2000/svg\"\n" "xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n" "version=\"1.0\"\n" "width=\"%d\"\n" "height=\"%d\"\n" "id=\"rocco\"\n" ">\n" ,dimx,dimy ); const double MINDIST = 1; const double MINDIST2 = 4; fprintf(fp,"<g id=\"arc_s\" style=\"fill:none;stroke:#0000E0;stroke-width:1;stroke-opacity:0.95;stroke-dasharray:none\">\n"); std::vector< edge >::iterator jj; for(jj=edges2.begin();jj!=edges2.end();++jj){ if( (nodes[ jj->i[0]].x<-dimx/2 || nodes[ jj->i[0]].x>dimx/2 || nodes[ jj->i[0]].y<0 || nodes[ jj->i[0]].y>dimy ) && (nodes[ jj->i[1]].x<-dimx/2 || nodes[ jj->i[1]].x>dimx/2 || nodes[ jj->i[1]].y<0 || nodes[ jj->i[1]].y>dimy ) ) continue; double dd = hp::e_dist( nodes[ jj->i[0]], nodes[ jj->i[1]] ); if(dd<MINDIST2) continue; hp::line l; l.from_points( nodes[ jj->i[0]], nodes[ jj->i[1]] ); hp::draw_arc(fp,l,nodes[ jj->i[0]], nodes[ jj->i[1]] ); } fprintf(fp,"</g>\n"); fprintf(fp,"<g id=\"arc_s\" style=\"fill:none;stroke:#000000;stroke-width:2;stroke-opacity:0.95;stroke-dasharray:none\">\n"); for(jj=edges.begin();jj!=edges.end();++jj){ if( (nodes[ jj->i[0]].x<-dimx/2 || nodes[ jj->i[0]].x>dimx/2 || nodes[ jj->i[0]].y<0 || nodes[ jj->i[0]].y>dimy ) && (nodes[ jj->i[1]].x<-dimx/2 || nodes[ jj->i[1]].x>dimx/2 || nodes[ jj->i[1]].y<0 || nodes[ jj->i[1]].y>dimy ) ) continue; double dd = hp::e_dist( nodes[ jj->i[0]], nodes[ jj->i[1]] ); if(dd<MINDIST) continue; hp::line l;l.from_points( nodes[ jj->i[0]], nodes[ jj->i[1]] ); hp::draw_arc(fp,l,nodes[ jj->i[0]], nodes[ jj->i[1]] ); } fprintf(fp,"</g>\n"); fprintf(fp,"</svg>\n"); fclose(fp); return 0; }
许可协议
我,本作品著作权人,特此采用以下许可协议发表本作品:
已授权您依据自由软件基金会发行的无固定段落及封面封底文字(Invariant Sections, Front-Cover Texts, and Back-Cover Texts)的GNU自由文件许可协议1.2版或任意后续版本的条款,复制、传播和/或修改本文件。该协议的副本请见“GNU Free Documentation License”。http://www.gnu.org/copyleft/fdl.htmlGFDLGNU Free Documentation Licensetruetrue |
本文件采用知识共享署名 3.0 未本地化版本许可协议授权。
- 您可以自由地:
- 共享 – 复制、发行并传播本作品
- 修改 – 改编作品
- 惟须遵守下列条件:
- 署名 – 您必须对作品进行署名,提供授权条款的链接,并说明是否对原始内容进行了更改。您可以用任何合理的方式来署名,但不得以任何方式表明许可人认可您或您的使用。
您可以选择您需要的许可协议。
GNU自由文档许可证1.2或更高版本 简体中文(已转写)
知识共享署名3.0未本地化版本 简体中文(已转写)
15 11 2007
文件历史
点击某个日期/时间查看对应时刻的文件。
日期/时间 | 缩略图 | 大小 | 用户 | 备注 | |
---|---|---|---|---|---|
当前 | 2007年11月15日 (四) 09:27 | 800 × 400(173 KB) | Rocchini | {{Information |Description=Stellated Eptagonal Tiling (Honeycomb) of Poincare Half-plane model |Source=self-made |Date=2007-11-15 |Author= Claudio Rocchini |Permission=CC-BY 3.0 }} | |
2007年11月15日 (四) 09:23 | 800 × 400(726 KB) | Rocchini | {{Information |Description=Stellated Eptagonal honeycomb (tiling) of the Poincare Half-Plane Model |Source=self-made |Date=2007-11-15 |Author= Claudio Rocchini |Permission=CC-BY 3.0 }} |
文件用途
以下3个页面使用本文件:
全域文件用途
以下其他wiki使用此文件:
- de.wikipedia.org上的用途
- en.wikipedia.org上的用途
- it.wikipedia.org上的用途
- ja.wikipedia.org上的用途
- ru.wikipedia.org上的用途
- uk.wikipedia.org上的用途
隐藏分类: