void cone (Scene &scene, int nseg, const Trafo& P, const ColorB* color) // // Adds a unit cone of radius 1 in x-y-plane with base at z = 1 and // tip at z = -1 to the scene. The mantle will be approximated by // nseg segments. The cone can be scaled by an arbitrary // transformation matrix P. // Optionally a color (precisely a pointer to ColorB) can be given to set the // color of the surface facets (defaults to NULL). // { int i,j; double theta = 0, dtheta = 2*M_PI/nseg; Vertex& tip = scene.AddVertex( P*Vertex(0,0,-1) ); Facet& base = scene.AddFacet(nseg); base(nseg-1) = &scene.AddVertex( P*Vertex(1,0,1) ); if (color) { base.SetColor(*color); base[nseg-1].SetColor(*color); tip.SetColor(*color); } for (i = 0, j = nseg-1; i < nseg; j = i++) { theta += dtheta; if (i != nseg-1) base(i) = &scene.AddVertex( P*Vertex(cos(theta),sin(theta),1) ); Facet& mantle = scene.AddFacet(3); mantle(2) = base(j); mantle(1) = base(i); mantle(0) = &tip; if (color) { mantle.SetColor(*color); base[i].SetColor(*color); } } }
void MpIcosahedron (Scene &scene, const Trafo &P, const ColorB* color) { const short faces[20][3] = { {1, 3, 2}, {1, 4, 3}, {1, 5, 4}, {1, 6, 5}, {1, 2, 6}, {2, 3, 7}, {3, 4, 8}, {4, 5, 9}, {5, 6, 10}, {6, 2, 11}, {7, 3, 8}, {8, 4, 9}, {9, 5, 10}, {10, 6, 11}, {11, 2, 7}, {7, 8, 12}, {8, 9, 12}, {9, 10, 12}, {10, 11, 12}, {11, 7, 12}}; const float g = 0.5*(1+sqrt(5.0)), g1 = g-1, p = 0.52573111211913360602567f; const float edges[12][3] = {{ 0, 0, g1/p }, { 2*p, 0, p }, { g1*p, 1, p }, { -g*p, g1, p }, { -g*p,-g1, p }, { g1*p, -1, p }, { g*p, g1, -p }, { -g1*p, 1, -p }, { -2*p, 0, -p }, { -g1*p, -1, -p }, { g*p,-g1, -p }, { 0, 0, -g1/p }}; Vertex *v[12]; int i; for (i = 0; i < 12; i++) { v[i] = &scene.AddVertex( P * Vertex(edges[i]) ); if (color) v[i]->SetColor(*color); } for (i = 0; i < 20; i++) { Facet &f = scene.AddFacet(3); for (int j = 0; j < 3; j++) f(j) = v[faces[i][2-j]-1]; if (color) f.SetColor(*color); } }
void stellate (Scene &body, float height) // // Adds starlike jags to every facet of the body. The tip // of a jag is placed in the given height over the center // of the facet. // { float nx,ny,nz,nk,nn,cx,cy,cz,h; Vertex* tip; Facet* f; int i,j,n; Scene stella; for (f = body.TheFacets(); f; f = f->NextFacet() ) { // calculate the normal form and the center of the facet f->Normal(nx,ny,nz,nk); f->Center(cx,cy,cz); // normalization of the normal vector to unit length nn = hypot(nx,ny,nz); // check if facet is degenerate if (nn == 0) continue; // add the tip vertex of the jag h = height / nn; tip = &stella.AddVertex( cx+h*nx, cy+h*ny, cz+h*nz ); // add three-sided facets for each side of the jag n = f->GetNumVertices(); for (i = 0, j = n-1; i < n; j = i++) { Facet& s = stella.AddFacet(3); s(0) = &stella.AddVertex( *(*f)(j) ); s(1) = &stella.AddVertex( *(*f)(i) ); s(2) = tip; } } // now clear the original body.Remove(); // and add the stellated body instead (duplicate vertices are now removed) body.AddScene(stella,Identity); }
void MpOctahedron (Scene &scene, const Trafo &P, const ColorB* color) { const short faces[8][3] = {{1, 2, 3}, {1, 3, 5}, {1, 5, 6}, {1, 6, 2}, {2, 6, 4}, {2, 4, 3}, {4, 6, 5}, {3, 4, 5}}; const float t = sqrt(2.0); const float edges[6][3] = {{0, 0, t}, { t, 0, 0}, {0, t, 0}, {0, 0, -t}, {-t, 0, 0}, {0, -t, 0}}; Vertex *v[6]; int i; for (i = 0; i < 6; i++) { v[i] = &scene.AddVertex( P * Vertex(edges[i]) ); if (color) v[i]->SetColor(*color); } for (i = 0; i < 8; i++) { Facet &f = scene.AddFacet(3); for (int j = 0; j < 3; j++) f(j) = v[faces[i][j]-1]; if (color) f.SetColor(*color); } }
void MpCube (Scene &scene, const Trafo &P, const ColorB* color) { const float edge[8][3] = { { 1, 1, 1}, { 1,-1, 1}, { 1,-1,-1}, { 1, 1,-1}, {-1, 1, 1}, {-1,-1, 1}, {-1,-1,-1}, {-1, 1,-1} }; const signed char face[6][4] = { { 0, 1, 2, 3}, { 0, 3, 7, 4}, { 0, 4, 5, 1}, { 2, 6, 7, 3}, { 1, 5, 6, 2}, { 4, 7, 6, 5} }; Vertex* v[8]; int i; // create 8 new vertices in this scene transforming them using P for (i = 0; i < 8; i++) { v[i] = &scene.AddVertex( P * Vertex(edge[i]) ); if (color) v[i]->SetColor(*color); } // create 6 new facets in this scene for (i = 0; i < 6; i++) { // add a new 4-sided facet to this scene Facet &f = scene.AddFacet(4); // link the edges in this facet to the corresponding vertices for (int j = 0; j < 4; j++) f(j) = v[face[i][j]]; // optionally set color if (color) f.SetColor(*color); } }
void Scene::Polygon (short n, float *x, float *y, float *z, long color, short mode) { // check for valid range of vertices if (n < 3 || n > MaxVertices) Matpack.Error("Scene::Polygon: number of vertices (%d) not within 3..%d", n,MaxVertices); Scene scn; // local scene copying the original settings scn.CopySettingsFrom(*this); Facet& f = scn.AddFacet(n); // add one facet to our local scene for (int i = 0; i < n; i++) f(i) = &scn.AddVertex(x[i],y[i],z[i]); scn.ClipBoxScene(); // clip at box scn.ObserveFacets(); // do observer transformation scn.ClipViewScene(); // clip at viewport scn.ProjectFacets(); // do perspective projection Facet* cf; // find the clipped facet for (cf = scn.facets; cf && cf->clipped; cf = cf->next); if ( cf ) { // something left after clipping ? for (int i = 0; i < n; i++) // copy projected vertices to polygon array pix[i] = (*cf)[i].p; Polygon(n,pix,color,mode); // draw the facet within the original scene } }
int MpWarpMatrixToSphere (Scene& S, Matrix& H, Vector& Pol, Vector& Azm, double r, const Trafo& T, int facet_culling, bool periodic, bool south_pole_cap, double h_south, bool north_pole_cap, double h_north, const ColorMap& cmap, double cmin, double cmax, int PolStride, int AzmStride) { int a,p,ncmap = 0; double x,y,z,pol,hr,sp,cp; double dz,scale = 0.0; bool usecolormap; int p1 = H.Rlo(), p2 = H.Rhi(), a1 = H.Clo(), a2 = H.Chi(); // check matrix and vector dimensions if (p1 != Pol.Lo() || p2 != Pol.Hi() || a1 != Azm.Lo() || a2 != Azm.Hi()) return 1; // check edge line stride values if (PolStride <= 0 || AzmStride <= 0) return 4; // evaluate facet culling flag int addFront = (facet_culling == Scene::Front) || (facet_culling == false), addBack = (facet_culling == Scene::Back) || (facet_culling == false); // number of facets in polar and azimuthal direction int np = p2-p1+1, na = a2-a1+1; // nothing that can be drawn if (np < 2 || na < 2) return 3; // pointer to vertices in two consecutive slices Vertex **top,**bot=0,**act; // allocate auxilliary storage if ( !(top = new Vertex*[na]) || !(bot = new Vertex*[na]) ) Matpack.Error("WarpMatrixToSphere: vector allocation failure"); // check if a colormap should be used if (cmap) { usecolormap = true; dz = cmax-cmin; ncmap = cmap.Size()-1; scale = (dz == 0.0) ? 0 : ncmap/dz; } else usecolormap = false; // Precompute sines and cosines of the azimuthal angles for the // sake of high performance Vector s,c; s = Sin(Azm); c = Cos(Azm); // loop through latitudes (polar angle) for ( p = p1, act = top; p <= p2; p++ ) { pol = Pol(p); sp = sin(pol); cp = cos(pol); // loop through longitudes (azimuthal angle) for ( a = a1; a <= a2; a++ ) { // warp transformation to sphere hr = H(p,a) + r; x = hr * cp * s(a); y = -hr * cp * c(a); z = hr * sp; // add vertices to scene storing a pointer to it // (and apply the global transformation) act[a-a1] = &S.AddVertex( T * Vertex((float)x,(float)z,(float)y) ); // set the vertex color if (usecolormap) { int cen = int((H(p,a)-cmin)*scale); MpForceRange(cen,0,ncmap); act[a-a1]->SetColor(cmap[cen]); } } // first slice or last slice - add triangles to create pole caps if ( (south_pole_cap && p == p1) || (north_pole_cap && p == p2) ) { int addF = false, addB = false; double h = 0.0; if (p == p1 && south_pole_cap) { addF = addBack; addB = addFront; h = -(r + h_south); } else if (p == p2 && north_pole_cap) { addF = addFront; addB = addBack; h = r + h_north; } // add vertices to scene storing a pointer to it // (and apply the global transformation) Vertex* v = &S.AddVertex(T * Vertex((float)0,(float)h,(float)0) ); // set the vertex color if (usecolormap) { int cen = int((h-cmin)*scale); MpForceRange(cen,0,ncmap); v->SetColor(cmap[cen]); } for (a = 0; a < na-1; a++) { // add with reverse orientation if (addB) { Facet &f = S.AddFacet(3); f(0) = v; f(1) = act[a]; f(2) = act[a+1]; SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride,true); // set color of facet according to colormap if (usecolormap) { int cen = int((H(p,a+a1)-cmin)*scale); MpForceRange(cen,0,ncmap); f.SetFrontColor(cmap[cen]); f.SetBackColor(cmap[cen]); } } // add with normal orientation if (addF) { Facet &f = S.AddFacet(3); f(2) = act[a]; f(1) = act[a+1]; f(0) = v; SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride); // set color of facet according to colormap if (usecolormap) { int cen = int((H(p,a+a1)-cmin)*scale); MpForceRange(cen,0,ncmap); f.SetFrontColor(cmap[cen]); f.SetBackColor(cmap[cen]); } } } // close sphere periodically in azimuthal direction if (periodic) { // add with opposite orientation if (addB) { Facet &f = S.AddFacet(3); f(0) = v; f(1) = act[na-1]; f(2) = act[0]; SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride,true); // set color of facet according to colormap if (usecolormap) { int cen = int((H(p,a1)-cmin)*scale); MpForceRange(cen,0,ncmap); f.SetFrontColor(cmap[cen]); f.SetBackColor(cmap[cen]); } } // add with normal orientation if (addF) { Facet &f = S.AddFacet(3); f(2) = act[na-1]; f(1) = act[0]; f(0) = v; SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride); // set color of facet according to colormap if (usecolormap) { int cen = int((H(p,a1)-cmin)*scale); MpForceRange(cen,0,ncmap); f.SetFrontColor(cmap[cen]); f.SetBackColor(cmap[cen]); } } } } // if ((south_pole_cap && p == p1) || (north_pole_cap && p == p2)) // // normal case: add quadrilaterals with top and bottom slices if (p != p1) { for (a = 0; a < na-1; a++) { // add with reverse orientation if (addBack) { Facet &f = S.AddFacet(4); f(0) = top[a]; f(1) = bot[a]; f(2) = bot[a+1]; f(3) = top[a+1]; SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride,true); // set color of facet according to colormap if (usecolormap) { int cen = int((H(p,a+a1)-cmin)*scale); MpForceRange(cen,0,ncmap); f.SetFrontColor(cmap[cen]); f.SetBackColor(cmap[cen]); } } // add with normal orientation if (addFront) { Facet &f = S.AddFacet(4); f(3) = top[a]; f(2) = bot[a]; f(1) = bot[a+1]; f(0) = top[a+1]; SetEdgeLineVisibility(f,a,AzmStride,p-p1,PolStride); // set color of facet according to colormap if (usecolormap) { int cen = int((H(p,a+a1)-cmin)*scale); MpForceRange(cen,0,ncmap); f.SetFrontColor(cmap[cen]); f.SetBackColor(cmap[cen]); } } } // close sphere periodically in azimuthal direction if (periodic) { // add with reverse orientation if (addBack) { Facet &f = S.AddFacet(4); f(0) = top[na-1]; f(1) = bot[na-1]; f(2) = bot[0]; f(3) = top[0]; SetEdgeLineVisibility(f,na-1,AzmStride,p-p1,PolStride,true); // set color of facet according to colormap if (usecolormap) { int cen = int((H(p,a1)-cmin)*scale); MpForceRange(cen,0,ncmap); f.SetFrontColor(cmap[cen]); f.SetBackColor(cmap[cen]); } } // add with normal orientation if (addFront) { Facet &f = S.AddFacet(4); f(3) = top[na-1]; f(2) = bot[na-1]; f(1) = bot[0]; f(0) = top[0]; SetEdgeLineVisibility(f,na-1,AzmStride,p-p1,PolStride); // set color of facet according to colormap if (usecolormap) { int cen = int((H(p,a1)-cmin)*scale); MpForceRange(cen,0,ncmap); f.SetFrontColor(cmap[cen]); f.SetBackColor(cmap[cen]); } } } } // if (p == p1) // // swap top with bot pointers act = bot; bot = top; top = act; } // for ( p = p1, ... ) // // remove auxilliary storage delete bot; delete top; // no problems occured return 0; }
void MpSurfaceBands (Scene& S, const Matrix& z, int direction, double width, const ColorMap& cmap, double cmin, double cmax) { Vertex *v0,*v1,*v2,*v3; double scale = 0.0; bool usecolormap; // the width of the bands MpForceRange(width,1e-3,1.0); // 0.5 is half the mesh unit width /= 2; int ncmap = 0, nx = z.Rows(), ny = z.Cols(); // check arguments if ( nx < 0 || ny < 0 ) return; // nothing to draw // check if a colormap should be used if (cmap) { usecolormap = true; ncmap = cmap.Size()-1; double dz = cmax - cmin; scale = (dz == 0.0) ? 0.0 : ncmap/dz; } else usecolormap = false; switch (direction) { case RowBandsGrid: case RowBands: { for ( int y = z.Clo(); y <= z.Chi(); y++ ) { int x = z.Rlo(); v0 = &S.AddVertex(y+width,z[x][y],x); v1 = &S.AddVertex(y-width,z[x][y],x); if (usecolormap) { int c = int((z[x][y]-cmin)*scale); if (c > ncmap) c = ncmap; else if (c < 0) c = 0; const ColorB &col = cmap[c]; v0->SetColor(col); v1->SetColor(col); } for ( ; x < z.Rhi(); x++) { // create facet Facet &f = S.AddFacet(4); v2 = &S.AddVertex(y-width,z[x+1][y],x+1); v3 = &S.AddVertex(y+width,z[x+1][y],x+1); f(0) = v0; f(1) = v1; f(2) = v2; f(3) = v3; v0 = v3; v1 = v2; // set edge line mask if (direction == RowBands) if (x == z.Rlo()) f.SetEdgeLineVisibility(Facet::Individual,0xb); // (1011=0xb) else if (x == z.Rhi()-1) f.SetEdgeLineVisibility(Facet::Individual,0xe); // (1110=0xe) else f.SetEdgeLineVisibility(Facet::Individual,0xa); // (1010=0xa) // set color of facet according to colormap if (usecolormap) { float cx,cy,cz; f.Center(cy,cz,cx); int c = int((cz-cmin)*scale); if (c > ncmap) c = ncmap; else if (c < 0) c = 0; const ColorB ¢er = cmap[c]; f.SetColor(center); c = int((z[x+1][y]-cmin)*scale); if (c > ncmap) c = ncmap; else if (c < 0) c = 0; const ColorB &col = cmap[c]; v2->SetColor(col); v3->SetColor(col); } } } break; } case ColumnBandsGrid: case ColumnBands: { for ( int x = z.Rlo(); x <= z.Rhi(); x++ ) { int y = z.Clo(); v1 = &S.AddVertex(y,z[x][y],x-width); v2 = &S.AddVertex(y,z[x][y],x+width); if (usecolormap) { int c = int((z[x][y]-cmin)*scale); const ColorB &col = cmap[c]; if (c > ncmap) c = ncmap; else if (c < 0) c = 0; v1->SetColor(col); v2->SetColor(col); } for ( ; y < z.Chi(); y++) { // create facet Facet &f = S.AddFacet(4); v0 = &S.AddVertex(y+1,z[x][y+1],x-width); v3 = &S.AddVertex(y+1,z[x][y+1],x+width); f(0) = v0; f(1) = v1; f(2) = v2; f(3) = v3; v1 = v0; v2 = v3; // set edge line mask if (direction == ColumnBands) if (y == z.Clo()) f.SetEdgeLineVisibility(Facet::Individual,0x7); // (0111=0x7) else if (y == z.Chi()-1) f.SetEdgeLineVisibility(Facet::Individual,0xd); // (1101=0xd) else f.SetEdgeLineVisibility(Facet::Individual,0x5); // (0101=0x5) // set color of facet according to colormap if (usecolormap) { float cx,cy,cz; f.Center(cy,cz,cx); int c = int((cz-cmin)*scale); if (c > ncmap) c = ncmap; else if (c < 0) c = 0; const ColorB ¢er = cmap[c]; f.SetColor(center); c = int((z[x][y+1]-cmin)*scale); if (c > ncmap) c = ncmap; else if (c < 0) c = 0; const ColorB &col = cmap[c]; v0->SetColor(col); v3->SetColor(col); } } } break; } default: Matpack.Error("MpSurfaceBands: Illegal value for direction argument"); break; } }