#help_index "Graphics/Math" public I64 gr_x_offsets[8] = {-1, 0, 1, -1, 1, -1, 0, 1}, gr_y_offsets[8] = {-1, -1, -1, 0, 0, 1, 1, 1}, gr_x_offsets2[4] = { 0, -1, 1, 0}, gr_y_offsets2[4] = {-1, 0, 0, 1}; public Bool Line(U8 *aux_data, I64 x1, I64 y1, I64 z1, I64 x2, I64 y2, I64 z2, Bool (*fp_plot)(U8 *aux, I64 x, I64 y, I64 z), I64 step=1, I64 start=0) {//Step through line segment calling callback. //Uses fixed-point. I64 i, j, d, dx = x2 - x1, dy = y2 - y1, dz = z2 - z1, _x, _y, _z, adx = AbsI64(dx), ady = AbsI64(dy), adz = AbsI64(dz); Bool first = TRUE; if (adx >= ady) { if (adx >= adz) { if (d = adx) { if (dx >= 0) dx = 0x100000000; else dx = -0x100000000; dy = dy << 32 / d; dz = dz << 32 / d; } } else { if (d = adz) { dx = dx << 32 / d; dy = dy << 32 / d; if (dz >= 0) dz = 0x100000000; else dz = -0x100000000; } } } else { if (ady >= adz) { if (d = ady) { dx = dx << 32 / d; if (dy >= 0) dy = 0x100000000; else dy = -0x100000000; dz = dz << 32 / d; } } else { if (d = adz) { dx = dx << 32 / d; dy = dy << 32 / d; if (dz >= 0) dz = 0x100000000; else dz = -0x100000000; } } } x1 <<= 32; y1 <<= 32; z1 <<= 32; for (j =0; j < start; j++) { x1 += dx; y1 += dy; z1 += dz; } if (step != 1 && step != 0) { dx *= step; dy *= step; dz *= step; d /= step; } for (i = start; i <= d; i++) { if ((_x != x1.i32[1] || _y != y1.i32[1] || _z != z1.i32[1] || first) && !(*fp_plot)(aux_data, x1.i32[1], y1.i32[1], z1.i32[1])) return FALSE; first = FALSE; _x = x1.i32[1]; _y = y1.i32[1]; _z = z1.i32[1]; x1 += dx; y1+=dy; z1+=dz; } if (step == 1 && (_x != x2 || _y != y2 || _z != z2) && !(*fp_plot)(aux_data, x2, y2, z2)) return FALSE; return TRUE; } #help_index "Graphics/Math/3D Transformation" public I64 *Mat4x4MulMat4x4Equ(I64 *dst, I64 *m1, I64 *m2) {//Multiply 4x4 matrices and store in dst. Uses fixed-point. //Conceptually, the transform m1 is applied after m2 I64 i, j, k; F64 sum; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { sum = 0; for (k = 0; k < 4; k++) sum += ToF64(m1[k + 4 * j]) * ToF64(m2[i + 4 * k]); dst[i + 4 * j] = sum / GR_SCALE; } } return dst; } public I64 *Mat4x4MulMat4x4New(I64 *m1, I64 *m2, CTask *mem_task=NULL) {//Multiply 4x4 matrices. Return MAlloced matrix. Uses fixed-point. //Conceptually, the transform m1 is applied after m2 return Mat4x4MulMat4x4Equ(MAlloc(sizeof(I64) * 16, mem_task), m1, m2); } public I64 *Mat4x4Equ(I64 *dst, I64 *src) {//Copy 4x4 Rot matrix. MemCopy(dst, src, sizeof(I64) * 16); return dst; } public I64 *Mat4x4New(I64 *src, CTask *mem_task=NULL) {//Return MAlloced copy of 4x4 Rot matrix. return Mat4x4Equ(MAlloc(sizeof(I64) * 16, mem_task), src); } public I64 *Mat4x4RotX(I64 *m, F64 phi) {//Rot matrix about X axis. Uses fixed-point. F64 my_cos = Cos(phi) * GR_SCALE, my_sin = Sin(phi) * GR_SCALE; I64 r[16], r2[16]; MemSet(r, 0, sizeof(r)); r[5] = my_cos; r[10] = my_cos; r[9] = my_sin; r[6] = -my_sin; r[0] = GR_SCALE; r[15] = GR_SCALE; return Mat4x4Equ(m, Mat4x4MulMat4x4Equ(r2, r, m)); } public I64 *Mat4x4RotY(I64 *m, F64 omega) {//Rot matrix about Y axis. Uses fixed-point. F64 my_cos = Cos(omega) * GR_SCALE, my_sin = Sin(omega) * GR_SCALE; I64 r[16], r2[16]; MemSet(r, 0, sizeof(r)); r[0] = my_cos; r[10] = my_cos; r[8] = -my_sin; r[2] = my_sin; r[5] = GR_SCALE; r[15] = GR_SCALE; return Mat4x4Equ(m, Mat4x4MulMat4x4Equ(r2, r, m)); } public I64 *Mat4x4RotZ(I64 *m, F64 theta) {//Rot matrix about Z axis. Uses fixed-point. F64 my_cos=Cos(theta)*GR_SCALE, my_sin=Sin(theta)*GR_SCALE; I64 r[16], r2[16]; MemSet(r, 0, sizeof(r)); r[0] = my_cos; r[5] = my_cos; r[4] = my_sin; r[1] = -my_sin; r[10] = GR_SCALE; r[15] = GR_SCALE; return Mat4x4Equ(m, Mat4x4MulMat4x4Equ(r2, r, m)); } public I64 *Mat4x4Scale(I64 *m, F64 s) {//Scale 4x4 matrix by value. I64 i; for (i = 0; i < 16; i++) m[i] *= s; return m; } public U0 DCThickScale(CDC *dc=gr.dc) {//Scale device context's thick by norm of transformation. I64 d; if (dc->flags & DCF_TRANSFORMATION) { if (dc->thick) { d = dc->thick * dc->r_norm + 0x80000000; //Round dc->thick = d.i32[1]; if (dc->thick < 1) dc->thick = 1; } } } public I64 *Mat4x4TranslationEqu(I64 *r, I64 x, I64 y, I64 z) {//Set translation values in 4x4 matrix. Uses fixed-point. r[0 * 4 + 3] = x << 32; r[1 * 4 + 3] = y << 32; r[2 * 4 + 3] = z << 32; r[3 * 4 + 3] = GR_SCALE; return r; } public I64 *Mat4x4TranslationAdd(I64 *r, I64 x, I64 y, I64 z) {//Add translation to 4x4 matrix. Uses fixed-point. r[0 * 4 + 3] += x << 32; r[1 * 4 + 3] += y << 32; r[2 * 4 + 3] += z << 32; r[3 * 4 + 3] = GR_SCALE; return r; } public Bool DCSymmetrySet(CDC *dc=gr.dc, I64 x1, I64 y1, I64 x2, I64 y2) {//2D. Set device context's symmetry. F64 d; if (y1 == y2 && x1 == x2) return FALSE; dc->sym.snx = y2 - y1; dc->sym.sny = x1 - x2; dc->sym.snz = 0; if (d = Sqrt(SqrI64(dc->sym.snx) + SqrI64(dc->sym.sny) + SqrI64(dc->sym.snz))) { d = GR_SCALE / d; dc->sym.snx *= d; dc->sym.sny *= d; dc->sym.snz *= d; } dc->sym.sx = x1; dc->sym.sy = y1; dc->sym.sz = 0; return TRUE; } public Bool DCSymmetry3Set(CDC *dc=gr.dc, I64 x1, I64 y1, I64 z1, I64 x2, I64 y2, I64 z2, I64 x3, I64 y3, I64 z3) {//3D. Set device context's symmetry. F64 d, x, y, z, xx, yy, zz; I64 xx1, yy1, zz1, xx2, yy2, zz2, *r; xx1 = x1 - x2; yy1 = y1 - y2; zz1 = z1 - z2; xx2 = x3 - x2; yy2 = y3 - y2; zz2 = z3 - z2; if (!xx1 && !yy1 && !zz1 || !xx2 && !yy2 && !zz2 || xx1 == xx2 && yy1 == yy2 && zz1 == zz2) return FALSE; x = yy1 * zz2 - zz1 * yy2; y = -xx1 * zz2 + zz1 * xx2; z = xx1 * yy2 - yy1 * xx2; if (dc->flags & DCF_TRANSFORMATION) { r = dc->r; xx = x * r[0] + y * r[1] + z * r[2]; yy = x * r[4] + y * r[5] + z * r[6]; zz = x * r[8] + y * r[9] + z * r[10]; x = xx; y = yy; z = zz; } if (d = Sqrt(Sqr(x) + Sqr(y) + Sqr(z))) { d = GR_SCALE / d; dc->sym.snx = d * x; dc->sym.sny = d * y; dc->sym.snz = d * z; } if (dc->flags & DCF_TRANSFORMATION) (*dc->transform)(dc, &x1, &y1, &z1); dc->sym.sx = x1; dc->sym.sy = y1; dc->sym.sz = z1; return TRUE; } public U0 DCReflect(CDC *dc, I64 *_x, I64 *_y, I64 *_z) {//Reflect 3D point about device context's symmetry. Uses fixed-point. I64 x = *_x << 32, y = *_y << 32, z = *_z << 32, xx = *_x - dc->sym.sx, yy = *_y - dc->sym.sy, zz = *_z - dc->sym.sz, d = (xx * dc->sym.snx + yy * dc->sym.sny + zz * dc->sym.snz) >> 16, xn, yn, zn, xx2, yy2, zz2; xn = d * dc->sym.snx >> 15; yn = d * dc->sym.sny >> 15; zn = d * dc->sym.snz >> 15; xx = x - xn; yy = y - yn; zz = z - zn; xx2 = x + xn; yy2 = y + yn; zz2 = z + zn; if (SqrI64(xx >> 16 - dc->sym.sx << 16) + SqrI64(yy >> 16 - dc->sym.sy << 16) + SqrI64(zz >> 16 - dc->sym.sz << 16) < SqrI64(xx2 >> 16 - dc->sym.sx << 16) + SqrI64(yy2 >> 16 - dc->sym.sy << 16) + SqrI64(zz2 >> 16 - dc->sym.sz << 16)) { *_x = xx.i32[1]; *_y = yy.i32[1]; *_z = zz.i32[1]; } else { *_x = xx2.i32[1]; *_y = yy2.i32[1]; *_z = zz2.i32[1]; } } #help_index "Graphics/Math" #define GR_SCALE1_BITS 24 #define GR_SCALE2_BITS 8 public Bool Circle(U8 *aux_data, I64 cx, I64 cy, I64 cz, I64 radius, Bool (*fp_plot)(U8 *aux, I64 x, I64 y, I64 z), I64 step=1, F64 start_radians=0, F64 len_radians=2*pi) {//Step through circle arc calling callback. I64 i, j, len = Ceil(len_radians * radius), x, y, x1, y1, s1, s2, c; F64 t; if (radius <= 0 || !step) return TRUE; t = 1.0 / radius; c = 1 << GR_SCALE1_BITS * Cos(t); if (step < 0) { step = -step; s2 = 1 << GR_SCALE1_BITS * Sin(t); s1 = -s2; } else { s1 = 1 << GR_SCALE1_BITS * Sin(t); s2 = -s1; } if (start_radians) { x = radius * Cos(start_radians); y = -radius * Sin(start_radians); } else { x = radius; y = 0; } x <<= GR_SCALE2_BITS; y <<= GR_SCALE2_BITS; for (i = 0; i <= len; i += step) { if (!(*fp_plot)(aux_data, cx + x >> GR_SCALE2_BITS, cy + y >> GR_SCALE2_BITS, cz)) return FALSE; for (j = 0; j < step; j++) { x1 =(c * x + s1 * y) >> GR_SCALE1_BITS; y1 =(s2 * x + c * y) >> GR_SCALE1_BITS; x = x1; y = y1; } } return TRUE; } public Bool Ellipse(U8 *aux_data, I64 cx, I64 cy, I64 cz, I64 x_radius, I64 y_radius, Bool (*fp_plot)(U8 *aux, I64 x, I64 y, I64 z), F64 rot_angle=0, I64 step=1, F64 start_radians=0, F64 len_radians=2*pi) {//Step through ellipse arc calling callback. I64 i, j, len, x, y, _x, _y, x1, y1, x2, y2, s1, s2, c, s12, s22, c2; F64 t; Bool first = TRUE; if (x_radius <= 0 || y_radius <= 0 || !step) return TRUE; if (x_radius >= y_radius) { t = 1.0 / x_radius; len = Ceil(len_radians * x_radius); } else { t = 1.0 / y_radius; len = Ceil(len_radians * y_radius); } c = 1 << GR_SCALE1_BITS * Cos(t); if (step < 0) { step = -step; s2 =1 << GR_SCALE1_BITS * Sin(t); s1 =-s2; } else { s1 = 1 << GR_SCALE1_BITS * Sin(t); s2 = -s1; } c2 = 1 << GR_SCALE1_BITS * Cos(rot_angle); s12 = 1 << GR_SCALE1_BITS * Sin(rot_angle); s22 = -s12; if (start_radians) { x = x_radius * Cos(start_radians); y = -x_radius * Sin(start_radians); } else { x = x_radius; y = 0; } x <<= GR_SCALE2_BITS; y <<= GR_SCALE2_BITS; x2 = x; y2 = y; y1 = y2 * y_radius / x_radius; x = (c2 * x2 + s12 * y1) >> GR_SCALE1_BITS; y = (s22 * x2 + c2 * y1) >> GR_SCALE1_BITS; for (i = 0; i <= len; i += step) { if ((x >> GR_SCALE2_BITS != _x || y >> GR_SCALE2_BITS != _y || first) && !(*fp_plot)(aux_data, cx + x >> GR_SCALE2_BITS, cy + y >> GR_SCALE2_BITS, cz)) return FALSE; _x = x >> GR_SCALE2_BITS; _y = y >> GR_SCALE2_BITS; first = FALSE; for (j = 0; j < step; j++) { x1 = (c * x2 + s1 * y2) >> GR_SCALE1_BITS; y1 = (s2 * x2 + c * y2) >> GR_SCALE1_BITS; x2 = x1; y2 = y1; y1 = y1 * y_radius/x_radius; x = (c2 * x1+ s12 * y1) >> GR_SCALE1_BITS; y = (s22 * x1 + c2 * y1) >> GR_SCALE1_BITS; } } return TRUE; } public Bool RegPoly(U8 *aux_data, I64 cx, I64 cy, I64 cz, I64 x_radius, I64 y_radius, I64 sides, Bool (*fp_plot)(U8 *aux, I64 x, I64 y, I64 z), F64 rot_angle=0, I64 step=1, F64 start_radians=0, F64 len_radians=2*pi) {//Step through regular polygon calling callback. I64 i, n, x, y, x1, y1, x2, y2, xx1, yy1, xx2, yy2, s1, s2, c, s12, s22, c2; F64 angle_step; if (sides <= 0 || x_radius <= 0 || y_radius <= 0) return TRUE; angle_step = 2 * pi / sides; n = len_radians * sides / (2 * pi); s1 = 1 << GR_SCALE1_BITS * Sin(angle_step); s2 = -s1; c = 1 << GR_SCALE1_BITS * Cos(angle_step); s12 = 1 << GR_SCALE1_BITS * Sin(rot_angle); s22 = -s12; c2 = 1 << GR_SCALE1_BITS * Cos(rot_angle); if (start_radians) { x = x_radius * Cos(start_radians); y = -x_radius * Sin(start_radians); } else { x = x_radius; y = 0; } x <<= GR_SCALE2_BITS; y <<= GR_SCALE2_BITS; x2 = x; y2 = y; y1 = y2 * y_radius / x_radius; x = (c2 * x2 + s12 * y1) >> GR_SCALE1_BITS; y = (s22 * x2 + c2 * y1) >> GR_SCALE1_BITS; xx1 = cx + x >> GR_SCALE2_BITS; yy1 = cy + y >> GR_SCALE2_BITS; for (i = 0; i < n; i++) { x1 = (c * x2 + s1 * y2) >> GR_SCALE1_BITS; y1 = (s2 * x2 + c * y2) >> GR_SCALE1_BITS; x2 = x1; y2 = y1; y1 = y1 * y_radius / x_radius; x = (c2 * x1 + s12 * y1) >> GR_SCALE1_BITS; y = (s22 * x1 + c2 * y1) >> GR_SCALE1_BITS; xx2 = cx + x >> GR_SCALE2_BITS; yy2 = cy + y >> GR_SCALE2_BITS; if (!Line(aux_data, xx1, yy1, cz, xx2, yy2, cz, fp_plot, step)) return FALSE; xx1 = xx2; yy1 = yy2; } return TRUE; } #help_index "Graphics/Data Types/D3I32;Math/Data Types/D3I32;Data Types/D3I32" public F64 D3I32Dist(CD3I32 *p1, CD3I32 *p2) {//Distance return Sqrt(SqrI64(p1->x - p2->x) + SqrI64(p1->y - p2->y) + SqrI64(p1->z - p2->z)); } public I64 D3I32DistSqr(CD3I32 *p1, CD3I32 *p2) {//Distance Squared return SqrI64(p1->x - p2->x) + SqrI64(p1->y - p2->y) + SqrI64(p1->z - p2->z); } public F64 D3I32Norm(CD3I32 *p) {//Norm return Sqrt(SqrI64(p->x) + SqrI64(p->y) + SqrI64(p->z)); } public I64 D3I32NormSqr(CD3I32 *p) {//Norm Squared return SqrI64(p->x) + SqrI64(p->y) + SqrI64(p->z); } #help_index "Graphics/Math" public Bool Bezier2(U8 *aux_data, CD3I32 *ctrl, Bool (*fp_plot)(U8 *aux, I64 x, I64 y, I64 z), Bool first=TRUE) {//Go in 2nd order bezier calling callback. I64 x, y, z, xx, yy, zz, dx, dy, dz, d_max; F64 x0 = ctrl[0].x, y0 = ctrl[0].y, z0 = ctrl[0].z, x1 = ctrl[1].x - x0, y1 = ctrl[1].y - y0, z1 = ctrl[1].z - z0, x2 = ctrl[2].x - x0, y2 = ctrl[2].y - y0, z2 = ctrl[2].z - z0, t, d = D3I32Dist(&ctrl[0], &ctrl[1]) + D3I32Dist(&ctrl[1], &ctrl[2]) + D3I32Dist(&ctrl[2], &ctrl[0]), s = 0.5 / d, t1, t2; xx = x0; yy = y0; zz = z0; if (first && !(*fp_plot)(aux_data, xx, yy, zz)) return FALSE; for (t = 0.0; t <= 1.0; t += s) { t1 = t * (1.0 - t); t2 = t * t; x = x0 + x1 * t1 + x2 * t2; y = y0 + y1 * t1 + y2 * t2; z = z0 + z1 * t1 + z2 * t2; dx = AbsI64(x - xx); dy = AbsI64(y - yy); dz = AbsI64(z - zz); if (dx > dy) d_max = dx; else d_max = dy; if (dz > d_max) d_max = dz; if (!d_max) s *= 1.1; else { s *= 0.9; if (!(*fp_plot)(aux_data, x, y, z)) return FALSE; xx = x; yy = y; zz = z; } } x = ctrl[2].x; y = ctrl[2].y; z = ctrl[2].z; if ((xx != x || yy != y || zz != z) && !(*fp_plot)(aux_data, x, y, z)) return FALSE; return TRUE; } public Bool Bezier3(U8 *aux_data, CD3I32 *ctrl, Bool (*fp_plot)(U8 *aux, I64 x, I64 y, I64 z), Bool first=TRUE) {//Go in 3rd order bezier calling callback. I64 x, y, z, xx, yy, zz, dx, dy, dz, d_max; F64 x0 = ctrl[0].x, y0 = ctrl[0].y, z0 = ctrl[0].z, x1 = ctrl[1].x - x0, y1 = ctrl[1].y - y0, z1 = ctrl[1].z - z0, x2 = ctrl[2].x - x0, y2 = ctrl[2].y - y0, z2 = ctrl[2].z - z0, x3 = ctrl[3].x - x0, y3 = ctrl[3].y - y0, z3 = ctrl[3].z - z0, t, d = D3I32Dist(&ctrl[0], &ctrl[1]) + D3I32Dist(&ctrl[1], &ctrl[2]) + D3I32Dist(&ctrl[2], &ctrl[3]) + D3I32Dist(&ctrl[3], &ctrl[0]), s = 0.5 / d, nt, t1, t2, t3; xx = x0; yy = y0; zz = z0; if (first && !(*fp_plot)(aux_data, xx, yy, zz)) return FALSE; for (t = 0.0; t <= 1.0; t += s) { nt = 1.0 - t; t1 = t * nt * nt; t2 = t * t * nt; t3 = t * t * t; x = x0 + x1 * t1 + x2 * t2 + x3 * t3; y = y0 + y1 * t1 + y2 * t2 + y3 * t3; z = z0 + z1 * t1 + z2 * t2 + z3 * t3; dx = AbsI64(x - xx); dy = AbsI64(y - yy); dz = AbsI64(z - zz); if (dx > dy) d_max = dx; else d_max = dy; if (dz > d_max) d_max = dz; if (!d_max) s *= 1.1; else { s *= 0.9; if (!(*fp_plot)(aux_data, x, y, z)) return FALSE; xx = x; yy = y; zz = z; } } x = ctrl[3].x; y = ctrl[3].y; z = ctrl[3].z; if ((xx != x || yy != y || zz != z) &&!(*fp_plot)(aux_data, x, y, z)) return FALSE; return TRUE; } public Bool BSpline2(U8 *aux_data, CD3I32 *ctrl, I64 count, Bool (*fp_plot)(U8 *aux, I64 x, I64 y, I64 z), Bool closed=FALSE) {//Go in 2nd order spline calling callback. I64 i, j; CD3I32 *c; Bool first; if (count < 3) return FALSE; first = TRUE; if (closed) { count++; c = MAlloc(sizeof(CD3I32) * (count * 2 - 1)); j = 1; for (i = 0; i < count - 2; i++) { c[j].x = (ctrl[i].x + ctrl[i + 1].x) / 2.0; c[j].y = (ctrl[i].y + ctrl[i + 1].y) / 2.0; c[j].z = (ctrl[i].z + ctrl[i + 1].z) / 2.0; j += 2; } c[j].x = (ctrl[0].x + ctrl[count - 2].x) / 2.0; c[j].y = (ctrl[0].y + ctrl[count - 2].y) / 2.0; c[j].z = (ctrl[0].z + ctrl[count - 2].z) / 2.0; c[0].x = (c[1].x + c[j].x) / 2.0; c[0].y = (c[1].y + c[j].y) / 2.0; c[0].z = (c[1].z + c[j].z) / 2.0; j = 2; for (i = 0; i < count - 2; i++) { c[j].x = (c[j - 1].x + c[j + 1].x) / 2.0; c[j].y = (c[j - 1].y + c[j + 1].y) / 2.0; c[j].z = (c[j - 1].z + c[j + 1].z) / 2.0; j += 2; } c[j].x = c[0].x; c[j].y = c[0].y; c[j].z = c[0].z; } else { c = MAlloc(sizeof(CD3I32) * (count * 2 - 1)); c[0].x = ctrl[0].x; c[0].y = ctrl[0].y; c[0].z = ctrl[0].z; c[count * 2 - 2].x = ctrl[count - 1].x; c[count * 2 - 2].y = ctrl[count - 1].y; c[count * 2 - 2].z = ctrl[count - 1].z; j = 1; for (i = 0; i < count - 1; i++) { c[j].x = (ctrl[i].x + ctrl[i + 1].x) / 2.0; c[j].y = (ctrl[i].y + ctrl[i + 1].y) / 2.0; c[j].z = (ctrl[i].z + ctrl[i + 1].z) / 2.0; j += 2; } j = 2; for (i = 0; i < count - 2; i++) { c[j].x = (c[j - 1].x + c[j + 1].x) / 2.0; c[j].y = (c[j - 1].y + c[j + 1].y) / 2.0; c[j].z = (c[j - 1].z + c[j + 1].z) / 2.0; j += 2; } } for (i = 0; i < count * 2 - 2; i += 2) { if (!Bezier2(aux_data, &c[i], fp_plot, first)) return FALSE; first = FALSE; } Free(c); return TRUE; } public Bool BSpline3(U8 *aux_data, CD3I32 *ctrl, I64 count, Bool (*fp_plot)(U8 *aux, I64 x, I64 y, I64 z), Bool closed=FALSE) {//Go in 3rd order spline calling callback. I64 i, j; F64 x, y, z; CD3I32 *c; Bool first; if (count < 3) return FALSE; first = TRUE; if (closed) { count++; c = MAlloc(sizeof(CD3I32) * (count * 3 - 2)); j = 1; for (i = 0; i < count - 2; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; c[j].x = (ctrl[i + 1].x - x) / 3.0 + x; c[j].y = (ctrl[i + 1].y - y) / 3.0 + y; c[j].z = (ctrl[i + 1].z - z) / 3.0 + z; j++; c[j].x = 2.0 * (ctrl[i + 1].x - x) / 3.0 + x; c[j].y = 2.0 * (ctrl[i + 1].y - y) / 3.0 + y; c[j].z = 2.0 * (ctrl[i + 1].z - z) / 3.0 + z; j += 2; } x = ctrl[count - 2].x; y = ctrl[count - 2].y; z = ctrl[count - 2].z; c[j].x = (ctrl[0].x - x) / 3.0 + x; c[j].y = (ctrl[0].y - y) / 3.0 + y; c[j].z = (ctrl[0].z - z) / 3.0 + z; j++; c[j].x = 2.0 * (ctrl[0].x - x) / 3.0 + x; c[j].y = 2.0 * (ctrl[0].y - y) / 3.0 + y; c[j].z = 2.0 * (ctrl[0].z - z) / 3.0 + z; c[0].x = (c[1].x + c[j].x) / 2.0; c[0].y = (c[1].y + c[j].y) / 2.0; c[0].z = (c[1].z + c[j].z) / 2.0; j = 3; for (i = 0; i < count - 2; i++) { c[j].x = (c[j - 1].x + c[j + 1].x) / 2.0; c[j].y = (c[j - 1].y + c[j + 1].y) / 2.0; c[j].z = (c[j - 1].z + c[j + 1].z) / 2.0; j += 3; } c[j].x = c[0].x; c[j].y = c[0].y; c[j].z = c[0].z; } else { c = MAlloc(sizeof(CD3I32) * (count * 3 - 2)); c[0].x = ctrl[0].x; c[0].y = ctrl[0].y; c[0].z = ctrl[0].z; c[count * 3 - 3].x = ctrl[count - 1].x; c[count * 3 - 3].y = ctrl[count - 1].y; c[count * 3 - 3].z = ctrl[count - 1].z; j = 1; for (i = 0; i < count - 1; i++) { x = ctrl[i].x; y = ctrl[i].y; z = ctrl[i].z; c[j].x = (ctrl[i + 1].x - x) / 3.0 + x; c[j].y = (ctrl[i + 1].y - y) / 3.0 + y; c[j].z = (ctrl[i + 1].z - z) / 3.0 + z; j++; c[j].x = 2.0 * (ctrl[i + 1].x - x) / 3.0 + x; c[j].y = 2.0 * (ctrl[i + 1].y - y) / 3.0 + y; c[j].z = 2.0 * (ctrl[i + 1].z - z) / 3.0 + z; j += 2; } j = 3; for (i = 0; i < count - 2; i++) { c[j].x = (c[j - 1].x + c[j + 1].x) / 2.0; c[j].y = (c[j - 1].y + c[j + 1].y) / 2.0; c[j].z = (c[j - 1].z + c[j + 1].z) / 2.0; j += 3; } } for (i = 0; i < count * 3 - 3; i += 3) { if (!Bezier3(aux_data, &c[i], fp_plot, first)) return FALSE; first = FALSE; } Free(c); return TRUE; } #define CC_LEFT 1 #define CC_RIGHT 2 #define CC_TOP 4 #define CC_BOTTOM 8 public Bool ClipLine(I64 *_x1, I64 *_y1, I64 *_x2, I64 *_y2, I64 left, I64 top, I64 right, I64 bottom) {//Clip x1,y1 x2,y2 with left,top,right,bottom. I64 x, y, x1 = *_x1, y1 = *_y1, x2 = *_x2, y2 = *_y2, cc, cc1, cc2; if (y1 > bottom) cc1 = CC_BOTTOM; else if (y1 < top) cc1 = CC_TOP; else cc1 = 0; if (x1 > right) cc1 |= CC_RIGHT; else if (x1 < left) cc1 |= CC_LEFT; if (y2 > bottom) cc2 = CC_BOTTOM; else if (y2 < top) cc2 = CC_TOP; else cc2 = 0; if (x2 > right) cc2 |= CC_RIGHT; else if (x2 < left) cc2 |= CC_LEFT; while (TRUE) { if (!(cc1 | cc2)) return TRUE; if (cc1 & cc2) return FALSE; if (cc1) cc = cc1; else cc = cc2; if (cc & CC_BOTTOM) { x = x1 + (x2 - x1) * (bottom - y1) / (y2 - y1); y = bottom; } else if (cc & CC_TOP) { x = x1 + (x2 - x1) * (top - y1) / (y2 - y1); y = top; } else if (cc & CC_RIGHT) { y = y1 + (y2 - y1) * (right - x1) / (x2 - x1); x = right; } else { y = y1 + (y2 - y1) * (left - x1) / (x2 - x1); x = left; } if (cc == cc1) { *_x1 = x1 = x; *_y1 = y1 = y; if (y1 > bottom) cc1 = CC_BOTTOM; else if (y1 < top) cc1 = CC_TOP; else cc1 = 0; if (x1 > right) cc1 |= CC_RIGHT; else if (x1 < left) cc1 |= CC_LEFT; } else { *_x2 = x2 = x; *_y2 = y2 = y; if (y2 > bottom) cc2 = CC_BOTTOM; else if (y2 < top) cc2 = CC_TOP; else cc2 = 0; if (x2 > right) cc2 |= CC_RIGHT; else if (x2 < left) cc2 |= CC_LEFT; } } }