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;
}
授權條款
我,本作品的著作權持有者,決定用以下授權條款發佈本作品:
| 已授權您依據自由軟體基金會發行的無固定段落、封面文字和封底文字GNU自由文件授權條款1.2版或任意後續版本,對本檔進行複製、傳播和/或修改。該協議的副本列在GNU自由文件授權條款中。http://www.gnu.org/copyleft/fdl.htmlGFDLGNU Free Documentation Licensetruetrue |
此檔案採用創用CC 姓名標示 3.0 未在地化版本授權條款。
- 您可以自由:
- 分享 – 複製、發佈和傳播本作品
- 重新修改 – 創作演繹作品
- 惟需遵照下列條件:
- 姓名標示 – 您必須指名出正確的製作者,和提供授權條款的連結,以及表示是否有對內容上做出變更。您可以用任何合理的方式來行動,但不得以任何方式表明授權條款是對您許可或是由您所使用。
您可以選擇您需要的授權條款。
說明
添加單行說明來描述出檔案所代表的內容
創用CC姓名標示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 的使用狀況