void Compute_Matrix_Transform (TRANSFORM *result, const MATRIX matrix) { register int i; for (i = 0; i < 4; i++) { (result->matrix)[i][0] = matrix[i][0]; (result->matrix)[i][1] = matrix[i][1]; (result->matrix)[i][2] = matrix[i][2]; (result->matrix)[i][3] = matrix[i][3]; } MInvers(result->inverse, result->matrix); }
void Polygon::Compute_Polygon(int number, Vector3d *points) { int i; DBL x, y, z, d; Vector3d o, u, v, w, N; MATRIX a, b; /* Create polygon data. */ if (Data == NULL) { Data = reinterpret_cast<POLYGON_DATA *>(POV_MALLOC(sizeof(POLYGON_DATA), "polygon points")); Data->References = 1; Data->Number = number; Data->Points = reinterpret_cast<Vector2d *>(POV_MALLOC(number*sizeof(Vector2d), "polygon points")); } else { throw POV_EXCEPTION_STRING("Polygon data already computed."); } /* Get polygon's coordinate system (one of the many possible) */ o = points[0]; /* Find valid, i.e. non-zero u vector. */ for (i = 1; i < number; i++) { u = points[i] - o; if (u.lengthSqr() > EPSILON) { break; } } if (i == number) { Set_Flag(this, DEGENERATE_FLAG); ;// TODO MESSAGE Warning("Points in polygon are co-linear. Ignoring polygon."); } /* Find valid, i.e. non-zero v and w vectors. */ for (i++; i < number; i++) { v = points[i] - o; w = cross(u, v); if ((v.lengthSqr() > EPSILON) && (w.lengthSqr() > EPSILON)) { break; } } if (i == number) { Set_Flag(this, DEGENERATE_FLAG); ;// TODO MESSAGE Warning("Points in polygon are co-linear. Ignoring polygon."); } u = cross(v, w); v = cross(w, u); u.normalize(); v.normalize(); w.normalize(); MIdentity(a); MIdentity(b); a[3][0] = -o[X]; a[3][1] = -o[Y]; a[3][2] = -o[Z]; b[0][0] = u[X]; b[1][0] = u[Y]; b[2][0] = u[Z]; b[0][1] = v[X]; b[1][1] = v[Y]; b[2][1] = v[Z]; b[0][2] = w[X]; b[1][2] = w[Y]; b[2][2] = w[Z]; MTimesC(Trans->inverse, a, b); MInvers(Trans->matrix, Trans->inverse); /* Project points onto the u,v-plane (3D --> 2D) */ for (i = 0; i < number; i++) { x = points[i][X] - o[X]; y = points[i][Y] - o[Y]; z = points[i][Z] - o[Z]; d = x * w[X] + y * w[Y] + z * w[Z]; if (fabs(d) > ZERO_TOLERANCE) { Set_Flag(this, DEGENERATE_FLAG); ;// TODO MESSAGE Warning("Points in polygon are not co-planar. Ignoring polygons."); } Data->Points[i][X] = x * u[X] + y * u[Y] + z * u[Z]; Data->Points[i][Y] = x * v[X] + y * v[Y] + z * v[Z]; } N = Vector3d(0.0, 0.0, 1.0); MTransNormal(S_Normal, N, Trans); S_Normal.normalize(); Compute_BBox(); }
void Sor::Compute_Sor(Vector2d *P, TraceThreadData *Thread) { int i, n; DBL *tmp_r1; DBL *tmp_r2; DBL *tmp_h1; DBL *tmp_h2; DBL A, B, C, D, w; DBL xmax, xmin, ymax, ymin; DBL k[4], x[4]; DBL y[2], r[2]; DBL c[3]; MATRIX Mat; /* Allocate Number segments. */ if (Spline == NULL) { Spline = new SOR_SPLINE; Spline->References = 1; Spline->Entry = new SOR_SPLINE_ENTRY[Number]; } else { throw POV_EXCEPTION_STRING("Surface of revolution segments are already defined."); } /* Allocate temporary lists. */ tmp_r1 = new DBL[Number]; tmp_r2 = new DBL[Number]; tmp_h1 = new DBL[Number]; tmp_h2 = new DBL[Number]; /* We want to know the size of the overall bounding cylinder. */ xmax = ymax = -BOUND_HUGE; xmin = ymin = BOUND_HUGE; /* Calculate segments, i.e. cubic patches. */ for (i = 0; i < Number; i++) { if ((fabs(P[i+2][Y] - P[i][Y]) < EPSILON) || (fabs(P[i+3][Y] - P[i+1][Y]) < EPSILON)) { throw POV_EXCEPTION_STRING("Incorrect point in surface of revolution."); } /* Use cubic interpolation. */ k[0] = P[i+1][X] * P[i+1][X]; k[1] = P[i+2][X] * P[i+2][X]; k[2] = (P[i+2][X] - P[i][X]) / (P[i+2][Y] - P[i][Y]); k[3] = (P[i+3][X] - P[i+1][X]) / (P[i+3][Y] - P[i+1][Y]); k[2] *= 2.0 * P[i+1][X]; k[3] *= 2.0 * P[i+2][X]; w = P[i+1][Y]; Mat[0][0] = w * w * w; Mat[0][1] = w * w; Mat[0][2] = w; Mat[0][3] = 1.0; Mat[2][0] = 3.0 * w * w; Mat[2][1] = 2.0 * w; Mat[2][2] = 1.0; Mat[2][3] = 0.0; w = P[i+2][Y]; Mat[1][0] = w * w * w; Mat[1][1] = w * w; Mat[1][2] = w; Mat[1][3] = 1.0; Mat[3][0] = 3.0 * w * w; Mat[3][1] = 2.0 * w; Mat[3][2] = 1.0; Mat[3][3] = 0.0; MInvers(Mat, Mat); /* Calculate coefficients of cubic patch. */ A = k[0] * Mat[0][0] + k[1] * Mat[0][1] + k[2] * Mat[0][2] + k[3] * Mat[0][3]; B = k[0] * Mat[1][0] + k[1] * Mat[1][1] + k[2] * Mat[1][2] + k[3] * Mat[1][3]; C = k[0] * Mat[2][0] + k[1] * Mat[2][1] + k[2] * Mat[2][2] + k[3] * Mat[2][3]; D = k[0] * Mat[3][0] + k[1] * Mat[3][1] + k[2] * Mat[3][2] + k[3] * Mat[3][3]; if (fabs(A) < EPSILON) A = 0.0; if (fabs(B) < EPSILON) B = 0.0; if (fabs(C) < EPSILON) C = 0.0; if (fabs(D) < EPSILON) D = 0.0; Spline->Entry[i].A = A; Spline->Entry[i].B = B; Spline->Entry[i].C = C; Spline->Entry[i].D = D; /* Get minimum and maximum radius**2 in current segment. */ y[0] = P[i+1][Y]; y[1] = P[i+2][Y]; x[0] = x[2] = P[i+1][X]; x[1] = x[3] = P[i+2][X]; c[0] = 3.0 * A; c[1] = 2.0 * B; c[2] = C; n = Solve_Polynomial(2, c, r, false, 0.0, Thread); while (n--) { if ((r[n] >= y[0]) && (r[n] <= y[1])) { x[n] = sqrt(r[n] * (r[n] * (r[n] * A + B) + C) + D); } } /* Set current segment's bounding cylinder. */ tmp_r1[i] = min(min(x[0], x[1]), min(x[2], x[3])); tmp_r2[i] = max(max(x[0], x[1]), max(x[2], x[3])); tmp_h1[i] = y[0]; tmp_h2[i] = y[1]; /* Keep track of overall bounding cylinder. */ xmin = min(xmin, tmp_r1[i]); xmax = max(xmax, tmp_r2[i]); ymin = min(ymin, tmp_h1[i]); ymax = max(ymax, tmp_h2[i]); /* fprintf(stderr, "bound spline segment %d: ", i); fprintf(stderr, "r = %f - %f, h = %f - %f\n", tmp_r1[i], tmp_r2[i], tmp_h1[i], tmp_h2[i]); */ } /* Set overall bounding cylinder. */ Radius1 = xmin; Radius2 = xmax; Height1 = ymin; Height2 = ymax; /* Get cap radius. */ w = tmp_h2[Number-1]; A = Spline->Entry[Number-1].A; B = Spline->Entry[Number-1].B; C = Spline->Entry[Number-1].C; D = Spline->Entry[Number-1].D; if ((Cap_Radius_Squared = w * (w * (A * w + B) + C) + D) < 0.0) { Cap_Radius_Squared = 0.0; } /* Get base radius. */ w = tmp_h1[0]; A = Spline->Entry[0].A; B = Spline->Entry[0].B; C = Spline->Entry[0].C; D = Spline->Entry[0].D; if ((Base_Radius_Squared = w * (w * (A * w + B) + C) + D) < 0.0) { Base_Radius_Squared = 0.0; } /* Get bounding cylinder. */ Spline->BCyl = Create_BCyl(Number, tmp_r1, tmp_r2, tmp_h1, tmp_h2); /* Get rid of temp. memory. */ delete[] tmp_h2; delete[] tmp_h1; delete[] tmp_r2; delete[] tmp_r1; }
void Compute_Polygon(POLYGON *Polyg, int Number, VECTOR *Points) { int i; DBL x, y, z, d; VECTOR o, u, v, w, N; MATRIX a, b; /* Create polygon data. */ if (Polyg->Data == NULL) { Polyg->Data = (POLYGON_DATA *)POV_MALLOC(sizeof(POLYGON_DATA), "polygon points"); Polyg->Data->References = 1; Polyg->Data->Number = Number; Polyg->Data->Points = (UV_VECT *)POV_MALLOC(Number*sizeof(UV_VECT), "polygon points"); } else { Error("Polygon data already computed."); } /* Get polygon's coordinate system (one of the many possible) */ Assign_Vector(o, Points[0]); /* Find valid, i.e. non-zero u vector. */ for (i = 1; i < Number; i++) { VSub(u, Points[i], o); if (VSumSqr(u) > EPSILON) { break; } } if (i == Number) { Set_Flag(Polyg, DEGENERATE_FLAG); Warning(0, "Points in polygon are co-linear. Ignoring polygon."); } /* Find valid, i.e. non-zero v and w vectors. */ for (i++; i < Number; i++) { VSub(v, Points[i], o); VCross(w, u, v); if ((VSumSqr(v) > EPSILON) && (VSumSqr(w) > EPSILON)) { break; } } if (i == Number) { Set_Flag(Polyg, DEGENERATE_FLAG); Warning(0, "Points in polygon are co-linear. Ignoring polygon."); } VCross(u, v, w); VCross(v, w, u); VNormalize(u, u); VNormalize(v, v); VNormalize(w, w); MIdentity(a); MIdentity(b); a[3][0] = -o[X]; a[3][1] = -o[Y]; a[3][2] = -o[Z]; b[0][0] = u[X]; b[1][0] = u[Y]; b[2][0] = u[Z]; b[0][1] = v[X]; b[1][1] = v[Y]; b[2][1] = v[Z]; b[0][2] = w[X]; b[1][2] = w[Y]; b[2][2] = w[Z]; MTimesC(Polyg->Trans->inverse, a, b); MInvers(Polyg->Trans->matrix, Polyg->Trans->inverse); /* Project points onto the u,v-plane (3D --> 2D) */ for (i = 0; i < Number; i++) { x = Points[i][X] - o[X]; y = Points[i][Y] - o[Y]; z = Points[i][Z] - o[Z]; d = x * w[X] + y * w[Y] + z * w[Z]; if (fabs(d) > ZERO_TOLERANCE) { Set_Flag(Polyg, DEGENERATE_FLAG); Warning(0, "Points in polygon are not co-planar. Ignoring polygons."); } Polyg->Data->Points[i][X] = x * u[X] + y * u[Y] + z * u[Z]; Polyg->Data->Points[i][Y] = x * v[X] + y * v[Y] + z * v[Z]; } Make_Vector(N, 0.0, 0.0, 1.0); MTransNormal(Polyg->S_Normal, N, Polyg->Trans); VNormalizeEq(Polyg->S_Normal); Compute_Polygon_BBox(Polyg); }