void Cone::Compute_Cylinder_Data() { DBL tmpf; Vector3d axis; axis = apex - base; tmpf = axis.length(); if (tmpf < EPSILON) { throw POV_EXCEPTION_STRING("Degenerate cylinder, base point = apex point."); // TODO FIXME - should a possible error } else { axis /= tmpf; Compute_Coordinate_Transform(Trans, base, axis, apex_radius, tmpf); } dist = 0.0; /* Recalculate the bounds */ Compute_BBox(); }
void Compute_Cylinder_Data(OBJECT *Object) { DBL tmpf; VECTOR axis; CONE *Cone = (CONE *)Object; VSub(axis, Cone->apex, Cone->base); VLength(tmpf, axis); if (tmpf < EPSILON) { Error("Degenerate cylinder, base point = apex point."); } else { VInverseScaleEq(axis, tmpf); Compute_Coordinate_Transform(Cone->Trans, Cone->base, axis, Cone->apex_radius, tmpf); } Cone->dist = 0.0; /* Recalculate the bounds */ Compute_Cone_BBox(Cone); }
void Lemon::Compute_Lemon_Data(GenericMessenger& messenger, pov_base::ITextStream *FileHandle, pov_base::ITextStream::FilePos & Token_File_Pos, int Token_Col_No ) { DBL len; Vector3d axis; /* Process the primitive specific information */ /* Find the axis and axis length */ axis = apex - base; len = axis.length(); if (len < EPSILON) { throw POV_EXCEPTION_STRING("Degenerate lemon."); } else { axis /= len; //normalize } /* adjust the various radius */ apex_radius /= len; base_radius /= len; inner_radius /= len; /* Determine alignment and scale */ Compute_Coordinate_Transform(Trans, base, axis, len, len); /* check constraint on inner_radius before solving the system of equation to find the * center of the minor circle of the torus * * base is at origin (0,0) * apex is at (0,1) * let's note base_radius as a, a>=0 * let's note apex_radius as b, b>=0 * let's note inner_radius as r, r>=0 * center of minor circle is at (x,y), with x<=0 * * (x-a)^2 + y^2 - r^2 = 0 : minor circle must pass on circle at base * (x-b)^2 + (1-y)^2 - r^2 = 0 : minor circle must pass on circle at apex * * r must be equal or greater than sqrt( a^4-2a^2(b^2-1)+(b^2+1)^2 ) / 2 * * then with f = sqrt((a^2-2ab+b^2-4r^2+1)/(a^2-2ab+b^2+1)) * * x = (a+b-f)/2 * y = (f(b-a)+1)/2 */ DBL low = sqrt(base_radius*base_radius*base_radius*base_radius - 2*base_radius*base_radius*(apex_radius*apex_radius-1.0)+(apex_radius*apex_radius+1.0)*(apex_radius*apex_radius+1.0))/2.0; if (inner_radius < low ) { std::stringstream o; inner_radius = low; o << "Inner (last) radius of lemon is too small. Minimal would be "<< (inner_radius*len) << ". Value has been adjusted."; messenger.WarningAt(kWarningGeneral, FileHandle->name(), Token_File_Pos.lineno, Token_Col_No, FileHandle->tellg().offset,"%s",o.str().c_str()); } DBL f = sqrt(-(base_radius*base_radius-2.0*base_radius*apex_radius+apex_radius*apex_radius-4.0*inner_radius*inner_radius+1.0)/(base_radius*base_radius-2.0*base_radius*apex_radius+apex_radius*apex_radius+1.0)); /* * Attention: valid HorizontalPosition is negative, always (or null) * It is of particular importance when using with torus evaluation and normal computation */ HorizontalPosition = (base_radius+apex_radius-f)/2.0; VerticalPosition = ((apex_radius-base_radius)*f+1.0)/2.0; }
void Disc::Compute_Disc() { Compute_Coordinate_Transform(Trans, center, normal, 1.0, 1.0); Compute_BBox(); }
void Cone::Compute_Cone_Data() { DBL tlen, len, tmpf; Vector3d tmpv, axis, origin; /* Process the primitive specific information */ /* Find the axis and axis length */ axis = apex - base; len = axis.length(); if (len < EPSILON) { throw POV_EXCEPTION_STRING("Degenerate cone/cylinder."); // TODO FIXME - should a possible error } else { axis /= len; } /* we need to trap that case first */ if (fabs(apex_radius - base_radius) < EPSILON) { /* What we are dealing with here is really a cylinder */ Set_Flag(this, CYLINDER_FLAG); Compute_Cylinder_Data(); return; } if (apex_radius < base_radius) { /* Want the bigger end at the top */ tmpv = base; base = apex; apex = tmpv; tmpf = base_radius; base_radius = apex_radius; apex_radius = tmpf; axis.invert(); } /* apex & base are different, yet, it might looks like a cylinder */ tmpf = base_radius * len / (apex_radius - base_radius); origin = base - axis * tmpf; tlen = tmpf + len; /* apex is always bigger here */ if (((apex_radius - base_radius)*len/tlen) < EPSILON) { /* What we are dealing with here is really a cylinder */ Set_Flag(this, CYLINDER_FLAG); Compute_Cylinder_Data(); return; } dist = tmpf / tlen; /* Determine alignment */ Compute_Coordinate_Transform(Trans, origin, axis, apex_radius, tlen); /* Recalculate the bounds */ Compute_BBox(); }
void Compute_Disc(DISC *Disc) { Compute_Coordinate_Transform(Disc->Trans, Disc->center, Disc->normal, 1.0, 1.0); Compute_Disc_BBox(Disc); }
void Compute_Cone_Data(OBJECT *Object) { DBL tlen, len, tmpf; VECTOR tmpv, axis, origin; CONE *Cone = (CONE *)Object; /* Process the primitive specific information */ if (fabs(Cone->apex_radius - Cone->base_radius) < EPSILON) { /* What we are dealing with here is really a cylinder */ Set_Flag(Cone, CYLINDER_FLAG); Compute_Cylinder_Data(Object); return; } if (Cone->apex_radius < Cone->base_radius) { /* Want the bigger end at the top */ Assign_Vector(tmpv,Cone->base); Assign_Vector(Cone->base,Cone->apex); Assign_Vector(Cone->apex,tmpv); tmpf = Cone->base_radius; Cone->base_radius = Cone->apex_radius; Cone->apex_radius = tmpf; } /* Find the axis and axis length */ VSub(axis, Cone->apex, Cone->base); VLength(len, axis); if (len < EPSILON) { Error("Degenerate cone/cylinder."); } else { VInverseScaleEq(axis, len); } /* Determine alignment */ tmpf = Cone->base_radius * len / (Cone->apex_radius - Cone->base_radius); VScale(origin, axis, tmpf); VSub(origin, Cone->base, origin); tlen = tmpf + len; Cone->dist = tmpf / tlen; Compute_Coordinate_Transform(Cone->Trans, origin, axis, Cone->apex_radius, tlen); /* Recalculate the bounds */ Compute_Cone_BBox(Cone); }