home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * MshPlanr.c - Test colinearity of control meshes/polygons. *
- *******************************************************************************
- * Written by Gershon Elber, Sep. 91. *
- ******************************************************************************/
-
- #include "cagd_loc.h"
-
- /*****************************************************************************
- * Computes a distance between two control points at given indices Index?. *
- * Only E2 or E3 point types are supported. *
- *****************************************************************************/
- CagdRType CagdDistanceTwoCtlPts(CagdRType **Points, int Index1, int Index2,
- CagdPointType PType)
- {
- switch (PType) {
- case CAGD_PT_E2_TYPE:
- return sqrt(SQR(Points[1][Index1] - Points[1][Index2]) +
- SQR(Points[2][Index1] - Points[2][Index2]));
- case CAGD_PT_E3_TYPE:
- return sqrt(SQR(Points[1][Index1] - Points[1][Index2]) +
- SQR(Points[2][Index1] - Points[2][Index2]) +
- SQR(Points[3][Index1] - Points[3][Index2]));
- default:
- FATAL_ERROR(CAGD_ERR_UNSUPPORT_PT);
- return 0.0;
- }
- }
-
- /*****************************************************************************
- * Fits a plane into the four points from Points indices Index?. Points may *
- * be either E2 or E3 only. *
- * Returns 0.0 if failed to fit a plane, otherwise a measure on the size of *
- * the mesh data (distance between points) isreturned. *
- *****************************************************************************/
- CagdRType CagdFitPlaneThruCtlPts(CagdPlaneStruct *Plane, CagdPointType PType,
- CagdRType **Points,
- int Index1, int Index2, int Index3, int Index4)
- {
- int i, j, Indices[4];
- CagdRType SizeMeasure,
- MaxDist = 0.0;
- CagdVecStruct V1, V2, V3;
-
- Indices[0] = Index1;
- Indices[1] = Index2;
- Indices[2] = Index3;
- Indices[3] = Index4;
-
- /* Find out the pair of vertices most seperated: */
- for (i = 0; i < 4; i++)
- for (j = i + 1; j < 4; j++) {
- CagdRType
- Dist = CagdDistanceTwoCtlPts(Points, Indices[i], Indices[j],
- PType);
- if (Dist > MaxDist) {
- MaxDist = Dist;
- Index1 = i;
- Index2 = j;
- }
- }
-
- if (MaxDist < EPSILON) return 0.0;
- SizeMeasure = MaxDist;
- MaxDist = 0.0;
-
- /* Find a third most seperated than the selected two. */
- for (i = 0; i < 4; i++)
- if (i != Index1 && i != Index2) {
- CagdRType
- Dist1 = CagdDistanceTwoCtlPts(Points, Indices[Index1],
- Indices[j], PType),
- Dist2 = CagdDistanceTwoCtlPts(Points, Indices[Index2],
- Indices[j], PType),
- Dist = MIN(Dist1, Dist2);
-
- if (Dist > MaxDist) {
- MaxDist = Dist;
- Index3 = i;
- }
- }
- if (MaxDist < EPSILON) return 0.0;
-
- /* Now we have the 3 most seperated vertices to fit a plane thru. */
-
- switch (PType) {
- case CAGD_PT_E2_TYPE:
- /* This is trivial since the plane must be Z = 0. */
- Plane -> Plane[0] = 0.0;
- Plane -> Plane[1] = 0.0;
- Plane -> Plane[2] = 1.0;
- Plane -> Plane[3] = 0.0;
- break;
- case CAGD_PT_E3_TYPE:
- /* Compute normal as a cross product of two vectors thru pts. */
- for (i = 0; i < 3; i++) {
- j = i + 1;
- V1.Vec[i] = Points[j][Index2] - Points[j][Index1];
- V2.Vec[i] = Points[j][Index3] - Points[j][Index2];
- }
- CROSS_PROD(V3.Vec, V1.Vec, V2.Vec);
- CAGD_NORMALIZE_VECTOR(V3);
- for (i = 0; i < 3; i++)
- Plane -> Plane[i] = V3.Vec[i];
-
- Plane -> Plane[3] = (-(V3.Vec[0] * Points[1][Index1] +
- V3.Vec[1] * Points[2][Index1] +
- V3.Vec[2] * Points[3][Index1]));
- break;
- default:
- FATAL_ERROR(CAGD_ERR_UNSUPPORT_PT);
- break;
- }
-
- return SizeMeasure;
- }
-
- /*****************************************************************************
- * Computes and returns distance between point Index and given plane which is *
- * assumed to be normalized, so that the A B C D plane normal has unit len.. *
- * Also assumed the Points are non rational with MaxDim dimension. *
- *****************************************************************************/
- CagdRType CagdDistPtPlane(CagdPlaneStruct *Plane, CagdRType **Points,
- int Index, int MaxDim)
- {
- int i;
- CagdRType
- R = Plane -> Plane[3];
-
- for (i = 0; i < MaxDim; i++)
- R += Plane -> Plane[i] * Points[i + 1][Index];
-
- return fabs(R);
- }
-
- /*****************************************************************************
- * Computes and returns distance between point Index and the line from first *
- * point in direction LineDir (usually the line direction to last the point). *
- * LineDir is assumed to be unit length normalized vector. *
- *****************************************************************************/
- static CagdRType CagdDistPtLine(CagdVecStruct *LineDir, CagdRType **Points,
- int Index, int MaxDim)
- {
- int i;
- CagdRType R;
- CagdVecStruct V1, V2;
-
- for (i = 0; i < MaxDim; i++)
- V1.Vec[i] = Points[i+1][Index] - Points[i+1][0];
- if (MaxDim < 3)
- V1.Vec[2] = 0.0;
-
- /* Let V1 be the vector from point zero to point index. Then the distance */
- /* from point Index the the line is: | (LineDir . V1) LineDir - V1 |. */
- V2 = *LineDir;
- R = DOT_PROD(V1.Vec, V2.Vec);
- CAGD_MULT_VECTOR(V2, R);
- CAGD_SUB_VECTOR(V2, V1);
-
- return CAGD_LEN_VECTOR(V2);
- }
-
- /*****************************************************************************
- * Test polygon colinearity by testing the distance of interior control *
- * points from the line connecting the two polygon end points. *
- * Returns a relative ratio of deviation from line relative to its length. *
- * Zero means all points are colinear. *
- * If two end points are same ( no line can be fit ) INFINITY is returned. *
- *****************************************************************************/
- CagdRType CagdEstimateCrvColinearity(CagdCrvStruct *Crv)
- {
- int i,
- MaxDim = 3,
- Length = Crv -> Length,
- Length1 = Length - 1;
- CagdRType LineLen,
- MaxDist = 0.0,
- **Points = Crv -> Points;
- CagdCrvStruct
- *CoercedCrv = NULL;
- CagdPointType
- PType = Crv ->PType;
- CagdVecStruct LineDir;
-
- switch (PType) { /* Convert the rational cases to non rational. */
- case CAGD_PT_P2_TYPE:
- CoercedCrv = CagdCoerceCrvTo(Crv, CAGD_PT_E2_TYPE);
- Points = CoercedCrv -> Points;
- PType = CoercedCrv -> PType;
- break;
- case CAGD_PT_P3_TYPE:
- CoercedCrv = CagdCoerceCrvTo(Crv, CAGD_PT_E3_TYPE);
- Points = CoercedCrv -> Points;
- PType = CoercedCrv -> PType;
- break;
- }
-
- switch (PType) {
- case CAGD_PT_E2_TYPE:
- LineDir.Vec[0] = Points[1][Length1] - Points[1][0];
- LineDir.Vec[1] = Points[2][Length1] - Points[2][0];
- LineDir.Vec[2] = 0.0;
- MaxDim = 2;
- break;
- case CAGD_PT_E3_TYPE:
- LineDir.Vec[0] = Points[1][Length1] - Points[1][0];
- LineDir.Vec[1] = Points[2][Length1] - Points[2][0];
- LineDir.Vec[2] = Points[3][Length1] - Points[3][0];
- break;
- default:
- FATAL_ERROR(CAGD_ERR_UNSUPPORT_PT);
- break;
- }
-
- LineLen = CAGD_LEN_VECTOR(LineDir);
- if (LineLen < EPSILON) {
- if (CoercedCrv != NULL)
- CagdCrvFree(CoercedCrv);
- return INFINITY;
- }
-
- CAGD_DIV_VECTOR(LineDir, LineLen);
-
- for (i = 1; i < Length1; i++) {
- CagdRType
- Dist = CagdDistPtLine(&LineDir, Points, i, MaxDim);
-
- if (Dist > MaxDist)
- MaxDist = Dist;
- }
-
- if (CoercedCrv != NULL)
- CagdCrvFree(CoercedCrv);
-
- return MaxDist / LineLen;
- }
-
- /*****************************************************************************
- * Test mesh colinearity by testing the distance of interior points from the *
- * plane thru 3 corner points. *
- * Returns a relative ratio of deviation from plane relative to its size. *
- * Zero means all points are coplanar. *
- * If end points are same ( no plane can be fit ) INFINITY is returned. *
- *****************************************************************************/
- CagdRType CagdEstimateSrfPlanarity(CagdSrfStruct *Srf)
- {
- int i,
- ULength = Srf -> ULength,
- ULength1 = ULength - 1,
- VLength = Srf -> VLength,
- VLength1 = VLength - 1;
- CagdRType
- PlaneSize = 0.0,
- MaxDist = 0.0,
- **Points = Srf -> Points;
- CagdSrfStruct
- *CoercedSrf = NULL;
- CagdPointType
- PType = Srf ->PType;
- CagdPlaneStruct Plane;
-
- switch (PType) { /* Convert the rational cases to non rational. */
- case CAGD_PT_P2_TYPE:
- case CAGD_PT_E2_TYPE:
- /* Trivial case - it is planar surface. */
- return 0.0;
- case CAGD_PT_P3_TYPE:
- CoercedSrf = CagdCoerceSrfTo(Srf, CAGD_PT_E3_TYPE);
- Points = CoercedSrf -> Points;
- PType = CoercedSrf -> PType;
- break;
- }
-
- switch (PType) {
- case CAGD_PT_E3_TYPE:
- PlaneSize = CagdFitPlaneThruCtlPts(&Plane, PType, Points,
- CAGD_MESH_UV(Srf, 0, 0),
- CAGD_MESH_UV(Srf, 0, VLength1),
- CAGD_MESH_UV(Srf, ULength1, 0),
- CAGD_MESH_UV(Srf, ULength1, VLength1));
- break;
- default:
- FATAL_ERROR(CAGD_ERR_UNSUPPORT_PT);
- break;
- }
-
- if (PlaneSize < EPSILON) {
- if (CoercedSrf != NULL)
- CagdSrfFree(CoercedSrf);
- return INFINITY;
- }
-
- for (i = ULength *VLength; i > 0; i--) {
- CagdRType
- Dist = CagdDistPtPlane(&Plane, Points, i, 3);
-
- if (Dist > MaxDist)
- MaxDist = Dist;
- }
-
- if (CoercedSrf != NULL)
- CagdSrfFree(CoercedSrf);
-
- return MaxDist / PlaneSize;
- }
-