void TSensorView::LineViewer(TDC& dc,PSHORTREAL pData) { m_xSize = m_nDimSize[0]-1; m_ySize = m_nDimSize[1]-1; m_yAdd = (int) (500L * m_ySize / m_xSize / 2); dc.SetWindowExt(TSize(m_xSize * 2 + m_ySize,500 + m_yAdd)); Grid3D(dc); if(m_nDimSize[1] == 1) for(int x = 0; x < m_nDimSize[0]; x++) { TPoint pt = Project2D(x,0,pData[x]); if (x) LINE(dc,pt); else MOVE(dc,pt); } else { TBrush br(SYSCOLOR(COLOR_BTNFACE)); dc.SelectObject(br); for (int y = 0; y < m_nDimSize[1]-1; y++) for (int x = 0; x < m_nDimSize[0]-1; x++) { TPoint pt[4] = { Project2D(x,y,pData[x + (LONGINT) m_nDimSize[0] * y]), Project2D(x+1,y,pData[x+1 + (LONGINT) m_nDimSize[0] * y]), Project2D(x+1,y+1,pData[x+1 + (LONGINT) m_nDimSize[0] * (y+1)]), Project2D(x,y+1,pData[x + (LONGINT) m_nDimSize[0] * (y+1)]) }; POLY(dc,pt,4); } } dc.RestorePen(); }
// finds the complex roots of the polynomial // _p : polynomial array, ascending powers [size: _k x 1] // _k : polynomials length (poly order = _k - 1) // _roots : resulting complex roots [size: _k-1 x 1] void POLY(_findroots)(T * _p, unsigned int _k, TC * _roots) { // find roots of polynomial using Bairstow's method (more // accurate and reliable than Durand-Kerner) POLY(_findroots_bairstow)(_p,_k,_roots); }
void TSensorView::ColumnViewer(TDC& dc,PSHORTREAL pData) { m_xSize = m_nDimSize[0]; m_ySize = m_nDimSize[1]; m_yAdd = (int) (500L * m_ySize / m_xSize / 2); dc.SetWindowExt(TSize(m_xSize * 2 + m_ySize,500 + m_yAdd)); Grid3D(dc); TBrush brGray(SYSCOLOR(COLOR_BTNFACE)), brWhite(SYSCOLOR(COLOR_BTNHIGHLIGHT)), brDark(SYSCOLOR(COLOR_BTNSHADOW)); for (int y = 0; y < m_nDimSize[1]; y++) for (int x = 0; x < m_nDimSize[0]; x++) { SHORTREAL r = pData[x + (LONGINT) m_nDimSize[0] * y]; TPoint pt[4] = { Project2D(x,y+1,r), Project2D(x+1,y+1,r), Project2D(x+1,y,r), Project2D(x,y,r) }; dc.SelectObject(brWhite); POLY(dc,pt,4); SHORTREAL r2 = y == m_nDimSize[1]-1 ? 0 : pData[x + (LONGINT) m_nDimSize[0] * (y+1)]; if(r2 < r) { pt[2] = Project2D(x+1,y+1,r2); pt[3] = Project2D(x,y+1,r2); dc.SelectObject(brGray); POLY(dc,pt,4); } r2 = x == m_nDimSize[0]-1 ? 0 : pData[x+1 + (LONGINT) m_nDimSize[0] * y]; if (r2 < r) { pt[0] = Project2D(x+1,y,r); pt[2] = Project2D(x+1,y+1,r2); pt[3] = Project2D(x+1,y,r2); dc.SelectObject(brDark); POLY(dc,pt,4); } } dc.RestoreBrush(); }
// finds the complex roots of the polynomial using the Durand-Kerner method // _p : polynomial array, ascending powers [size: _k x 1] // _k : polynomials length (poly order = _k - 1) // _roots : resulting complex roots [size: _k-1 x 1] void POLY(_findroots_durandkerner)(T * _p, unsigned int _k, TC * _roots) { if (_k < 2) { fprintf(stderr,"%s_findroots_durandkerner(), order must be greater than 0\n", POLY_NAME); exit(1); } else if (_p[_k-1] != 1) { fprintf(stderr,"%s_findroots_durandkerner(), _p[_k-1] must be equal to 1\n", POLY_NAME); exit(1); } unsigned int i; unsigned int num_roots = _k-1; T r0[num_roots]; T r1[num_roots]; // find intial magnitude float g = 0.0f; float gmax = 0.0f; for (i=0; i<_k; i++) { g = cabsf(_p[i]); if (i==0 || g > gmax) gmax = g; } // initialize roots T t0 = 0.9f * (1 + gmax) * cexpf(_Complex_I*1.1526f); T t = 1.0f; for (i=0; i<num_roots; i++) { r0[i] = t; t *= t0; } unsigned int max_num_iterations = 50; int continue_iterating = 1; unsigned int j, k; T f; T fp; //for (i=0; i<num_iterations; i++) { i = 0; while (continue_iterating) { #if 0 printf("%s_findroots(), i=%3u :\n", POLY_NAME, i); for (j=0; j<num_roots; j++) printf(" r[%3u] = %12.8f + j*%12.8f\n", j, crealf(r0[j]), cimagf(r0[j])); #endif for (j=0; j<num_roots; j++) { f = POLY(_val)(_p,_k,r0[j]); fp = 1; for (k=0; k<num_roots; k++) { if (k==j) continue; fp *= r0[j] - r0[k]; } r1[j] = r0[j] - f / fp; } // stop iterating if roots have settled float delta=0.0f; T e; for (j=0; j<num_roots; j++) { e = r0[j] - r1[j]; delta += crealf(e*conjf(e)); } delta /= num_roots * gmax; #if 0 printf("delta[%3u] = %12.4e\n", i, delta); #endif if (delta < 1e-6f || i == max_num_iterations) continue_iterating = 0; memmove(r0, r1, num_roots*sizeof(T)); i++; } for (i=0; i<_k; i++) _roots[i] = r1[i]; }
// finds the complex roots of the polynomial // _p : polynomial array, ascending powers [size: _k x 1] // _k : polynomials length (poly order = _k - 1) // _roots : resulting complex roots [size: _k-1 x 1] void POLY(_findroots)(T * _p, unsigned int _k, TC * _roots) { POLY(_findroots_bairstow)(_p,_k,_roots); }
// finds the complex roots of the polynomial using Bairstow's method // _p : polynomial array, ascending powers [size: _k x 1] // _k : polynomials length (poly order = _k - 1) // _roots : resulting complex roots [size: _k-1 x 1] void POLY(_findroots_bairstow)(T * _p, unsigned int _k, TC * _roots) { T p0[_k]; // buffer 0 T p1[_k]; // buffer 1 T * p = NULL; // input polynomial T * pr = NULL; // output (reduced) polynomial unsigned int i; unsigned int k=0; // output roots counter memmove(p0, _p, _k*sizeof(T)); T u, v; unsigned int n = _k; // input counter (decrementer) unsigned int r = _k % 2; // polynomial length odd? (order even?) unsigned int L = (_k-r)/2; // semi-length for (i=0; i<L-1+r; i++) { // set polynomial and reduced polynomial buffer pointers p = (i % 2) == 0 ? p0 : p1; pr = (i % 2) == 0 ? p1 : p0; // initial estimates for u, v // TODO : ensure no division by zero if (p[n-1] == 0) { fprintf(stderr,"warning: poly_findroots_bairstow(), irreducible polynomial"); p[n-1] = 1e-12; } u = p[n-2] / p[n-1]; v = p[n-3] / p[n-1]; // compute factor using Bairstow's recursion POLY(_findroots_bairstow_recursion)(p,n,pr,&u,&v); // compute complex roots of x^2 + u*x + v TC r0 = 0.5f*(-u + csqrtf(u*u - 4.0*v)); TC r1 = 0.5f*(-u - csqrtf(u*u - 4.0*v)); // append result to output _roots[k++] = r0; _roots[k++] = r1; #if 0 // print debugging info unsigned int j; printf("initial polynomial:\n"); for (j=0; j<n; j++) printf(" p[%3u] = %12.8f + j*%12.8f\n", j, crealf(p[j]), cimagf(p[j])); printf("polynomial factor: x^2 + u*x + v\n"); printf(" u : %12.8f + j*%12.8f\n", crealf(u), cimagf(u)); printf(" v : %12.8f + j*%12.8f\n", crealf(v), cimagf(v)); printf("roots:\n"); printf(" r0 : %12.8f + j*%12.8f\n", crealf(r0), cimagf(r0)); printf(" r1 : %12.8f + j*%12.8f\n", crealf(r1), cimagf(r1)); printf("reduced polynomial:\n"); for (j=0; j<n-2; j++) printf(" pr[%3u] = %12.8f + j*%12.8f\n", j, crealf(pr[j]), cimagf(pr[j])); #endif // decrement new (reduced) polynomial size by 2 n -= 2; } if (r==0) { assert(n==2); _roots[k++] = -pr[0]/pr[1]; } //assert( k == _k-1 ); }
/* This gets called whenever the input, the size, changes. Create a cube with the given side length. */ static PComputeStatus compute(PPInput *input, PPOutput output, void *state) { enum { MY_OBJECT, MY_GEOMETRY }; /* Node labels. */ PONode *obj, *geo; real32 radius = p_input_real32(input[0]); /* Read out the radius. */ uint32 end_splits = p_input_uint32(input[1]); /* And the top/bottom tesselation level. */ uint32 side_splits = p_input_uint32(input[2]); /* And the side tesselation level. */ uint32 quad_levels; boolean uv_map = p_input_boolean(input[3]); real64 angle, y, r; uint32 i, j, pos, bc, tc; PNGLayer *lay, *ulay, *vlay; if(side_splits < 2) return P_COMPUTE_DONE; obj = p_output_node_create(output, V_NT_OBJECT, MY_OBJECT); p_node_set_name(obj, "sphere"); geo = p_output_node_create(output, V_NT_GEOMETRY, MY_GEOMETRY); p_node_set_name(geo, "sphere-geo"); p_node_o_link_set(obj, geo, "geometry", 0); quad_levels = side_splits - 2; /* Top and bottom layers are triangles. */ /* Create outer vertices. */ lay = p_node_g_layer_find(geo, "vertex"); for(j = 0; j <= quad_levels; j++) { y = radius * sin(-M_PI/2 + M_PI * (j + 1) / side_splits); r = radius * cos(-M_PI/2 + M_PI * (j + 1) / side_splits); for(i = 0; i < end_splits; i++) { angle = 2 * M_PI * (i / (real64) end_splits); p_node_g_vertex_set_xyz(lay, j * end_splits + i, r * cos(angle), y, r * -sin(angle)); } } bc = (quad_levels + 1) * end_splits; p_node_g_vertex_set_xyz(lay, bc, 0.0, -radius, 0.0); tc = bc + 1; p_node_g_vertex_set_xyz(lay, tc, 0.0, radius, 0.0); lay = p_node_g_layer_find(geo, "polygon"); /* Create bottom triangles. */ for(i = 0; i < end_splits; i++) POLY("bottom triangle", lay, i, i, (i + 1) % end_splits, bc, ~0u); /* Create intermediary quads, if any. */ for(i = 0; i < quad_levels; i++) { pos = i * end_splits; for(j = 0; j < end_splits; j++) { POLY("side quad", lay, end_splits + pos + j, pos + j, pos + j + end_splits, pos + (j + 1) % end_splits + end_splits, pos + (j + 1) % end_splits); } } /* Create top triangles. */ for(i = 0; i < end_splits; i++) POLY("top triangle", lay, (quad_levels + 1) * end_splits + i, tc - 2 - end_splits + (i + 1) % end_splits, tc - 2 - end_splits + i, tc, ~0u); if(uv_map) { uint32 poly; real64 u[4], v[4]; ulay = p_node_g_layer_create(geo, "map_u", VN_G_LAYER_POLYGON_CORNER_REAL, 0, 0.0f); vlay = p_node_g_layer_create(geo, "map_v", VN_G_LAYER_POLYGON_CORNER_REAL, 0, 0.0f); /* Texture-map the bottom polygons, the ones touching the "south pole". */ for(i = poly = 0; i < end_splits; i++, poly++) { compute_quad_uv(u, v, i, 0, end_splits, side_splits); p_node_g_polygon_set_corner_real64(ulay, poly, u[0], u[1], 0.5, 0.0); p_node_g_polygon_set_corner_real64(vlay, poly, /* V values are the same for every triangle. Flipped, though. */ v[1], v[1], 1.0, 0.0); } /* Texture map the main polygons, the ones not touching a pole vertex. */ for(j = 0; j < quad_levels; j++) { for(i = 0; i < end_splits; i++, poly++) { compute_quad_uv(u, v, i, j + 1, end_splits, side_splits); p_node_g_polygon_set_corner_real64(ulay, poly, u[0], u[1], u[2], u[3]); p_node_g_polygon_set_corner_real64(vlay, poly, v[0], v[1], v[2], v[3]); } } /* Texture-map the top polygons, the ones touching the "north pole". */ for(i = 0; i < end_splits; i++, poly++) { compute_quad_uv(u, v, i, side_splits, end_splits, side_splits); /* Works for tris to, if you're careful. */ p_node_g_polygon_set_corner_real64(ulay, poly, u[0], u[1], u[2], u[3]); p_node_g_polygon_set_corner_real64(vlay, poly, v[1], v[1], 0.0, 0.0); } } p_node_g_crease_set_vertex(geo, NULL, ~0u); p_node_g_crease_set_edge(geo, NULL, ~0u); return P_COMPUTE_DONE; /* Sleep until size changes. */ }
/* This gets called whenever the input, the size, changes. Create a cube with the given side length. */ static PComputeStatus compute(PPInput *input, PPOutput output, void *state) { enum { MY_OBJECT, MY_GEOMETRY }; /* Node labels. */ PONode *obj, *geo; real32 height = p_input_real32(input[0]); /* Read out the size. */ uint32 end_splits = p_input_uint32(input[1]); /* And the top/bottom tesselation level. */ uint32 side_splits = p_input_uint32(input[2]); /* And the side tesselation level. */ real64 angle, x, y; uint32 i, j, pos, poly, corner, bc, tc; uint32 v0, v1, v2, v3; PNGLayer *lay; obj = p_output_node_create(output, V_NT_OBJECT, MY_OBJECT); p_node_set_name(obj, "cylinder"); geo = p_output_node_create(output, V_NT_GEOMETRY, MY_GEOMETRY); p_node_o_link_set(obj, geo, "geometry", 0); /* Create outer vertices. */ lay = p_node_g_layer_find(geo, "vertex"); for(j = 0; j <= side_splits; j++) { y = j * height / side_splits; for(i = 0; i < end_splits; i++, pos++) { angle = 2 * M_PI * (i / (double) end_splits); p_node_g_vertex_set_xyz(lay, j * end_splits + i, cos(angle), y, -sin(angle)); } } /* Create bottom center vertex. */ bc = (side_splits + 1) * end_splits; p_node_g_vertex_set_xyz(lay, bc, 0.0, 0.0, 0.0); /* Create top center. It's at bc+1. */ tc = bc + 1; p_node_g_vertex_set_xyz(lay, tc, 0.0, height, 0.0); /* Create bottom surface. */ lay = p_node_g_layer_find(geo, "polygon"); for(i = 0; i < end_splits; i++) POLY("bottom", lay, i, i, (i + 1) % end_splits, bc, ~0u); /* Create side polygons (quads). */ for(j = 0; j < side_splits; j++) { pos = j * end_splits; for(i = 0; i < end_splits; i++) { POLY("side", lay, end_splits + j * end_splits + i, pos + i + end_splits, pos + (i + 1) % end_splits + end_splits, pos + (i + 1) % end_splits, pos + i); } } /* Create top surface. */ pos = tc - 1 - end_splits; for(i = 0; i < end_splits; i++) POLY("top", lay, end_splits + side_splits * end_splits + i, pos + (i + 1) % end_splits, pos + i, tc, ~0u); p_node_g_crease_set_vertex(geo, NULL, ~0u); p_node_g_crease_set_edge(geo, NULL, ~0u); return P_COMPUTE_DONE; /* Sleep until size changes. */ }