/***************************************************************************** * DESCRIPTION: M * Apply Bezier subdivision to the given curve at parameter value t, and M * save the result in data LPoints/RPoints. Note this function could also be M * called from a B-spline curve with a Bezier knot sequence. M * * * PARAMETERS: M * Points: To subdivide at parametr value t. M * LPoints, RPoints: Where the results are kept. M * Length: Of this Bezier curve. M * PType: Points types we have here. M * t: Parameter value to subdivide curve at. M * * * RETURN VALUE: M * void M * * * SEE ALSO: M * BzrCrvSubdivAtParam, BspCrvSubdivCtlPoly, BzrCrvSubdivCtlPolyStep M * * * KEYWORDS: M * BzrCrvSubdivCtlPoly M *****************************************************************************/ void BzrCrvSubdivCtlPoly(CagdRType * const *Points, CagdRType **LPoints, CagdRType **RPoints, int Length, CagdPointType PType, CagdRType t) { CagdBType IsNotRational = !CAGD_IS_RATIONAL_PT(PType); int i, j, l, MaxCoord = CAGD_NUM_OF_PT_COORD(PType); CagdRType t1 = 1.0 - t; /* Copy Points into RPoints, so we can apply the recursive algo. to it. */ for (j = IsNotRational; j <= MaxCoord; j++) IRIT_GEN_COPY(RPoints[j], Points[j], Length * sizeof(CagdRType)); for (j = IsNotRational; j <= MaxCoord; j++) LPoints[j][0] = Points[j][0]; /* Apply the recursive algorithm to RPoints, and update LPoints with the */ /* temporary results. Note we updated the first point of LPoints above. */ for (i = 1; i < Length; i++) { for (l = 0; l < Length - i; l++) for (j = IsNotRational; j <= MaxCoord; j++) RPoints[j][l] = RPoints[j][l] * t1 + RPoints[j][l + 1] * t; /* Copy temporary result to LPoints: */ for (j = IsNotRational; j <= MaxCoord; j++) LPoints[j][i] = RPoints[j][0]; } }
/***************************************************************************** * DESCRIPTION: * * Finds the tangent vector to the curve at each parameter. * * * * PARAMETERS: * * Crv: The input curve. * * TangentsVector: An array for the tangent at each parameter. * * CrvEval: The value of the curve at each parameter. * * * * RETURN VALUE: * * CagdBType: TRUE for Sucssess. * *****************************************************************************/ static CagdBType FindTangentsVec( const CagdCrvStruct *Crv, CagdVType TangentsVector[CAGD_CM_MAX_SAMPLE_NUM], CagdVType CrvEval[CAGD_CM_MAX_SAMPLE_NUM]) { int i; CagdRType StartCrvPar, EndCrvPar, Par, *Pt, DPt[CAGD_MAX_PT_SIZE], DPar; CagdCrvStruct *TanCrv = CagdCrvDeriveScalar(Crv); CagdPointType PType = TanCrv -> PType; CagdCrvDomain(Crv, &StartCrvPar, &EndCrvPar); DPar = (EndCrvPar - StartCrvPar) / (GlblNumberOfSamples - 1); for (i = 0, Par = StartCrvPar; i < GlblNumberOfSamples; i++, Par += DPar) { if (Par > EndCrvPar) /* Due to floating point roundoff errors. */ Par = EndCrvPar; Pt = CagdCrvEval(TanCrv, Par); IRIT_GEN_COPY(DPt, Pt, sizeof(CagdRType) * CAGD_MAX_PT_SIZE); Pt = CagdCrvEval(Crv , Par); CagdCoerceToE3(CrvEval[i], &Pt, -1, TanCrv -> PType); if (CAGD_IS_RATIONAL_CRV(TanCrv)) { int j; for (j = 1; j <= IRIT_MIN(CAGD_NUM_OF_PT_COORD(PType), 3); j++) { if (Pt[0] == 0) TangentsVector[i][j - 1] = 0.0; else TangentsVector[i][j - 1] = (DPt[j] * Pt[0] - Pt[j] * DPt[0]) / IRIT_SQR(Pt[0]); } } else { Pt = DPt; CagdCoerceToE3(TangentsVector[i], &Pt, -1, PType); } IRIT_PT_NORMALIZE(TangentsVector[i]); } CagdCrvFree(TanCrv); return TRUE; }
/***************************************************************************** * DESCRIPTION: * * Main module of skeleton - Read command line and do what is needed... * * * * PARAMETERS: * * FileNames: Files to open and read, as a vector of strings. * * NumFiles: Length of the FileNames vector. * * * * RETURN VALUE: * * bool: false - fail, true - success. * *****************************************************************************/ bool CGSkelProcessIritDataFiles(CString &FileNames, int NumFiles, std::vector<PolygonalObject>& outObjects, int polygonFineness) { IPObjectStruct *PObjects; IrtHmgnMatType CrntViewMat; /* Get the data files: */ IPSetFlattenObjects(FALSE); // Boris' patch: convert FileNames to an array of size 1 // then convert it from wide char to char LPCTSTR* tmp1 = (LPCTSTR*)&FileNames; char tmp2[201]; char* tmp3[1] = { tmp2 }; wcstombs(tmp2, *tmp1, 200); if ((PObjects = IPGetDataFiles(tmp3, 1/*NumFiles*/, TRUE, FALSE)) == NULL) return false; // End of patch PObjects = IPResolveInstances(PObjects); if (IPWasPrspMat) MatMultTwo4by4(CrntViewMat, IPViewMat, IPPrspMat); else IRIT_GEN_COPY(CrntViewMat, IPViewMat, sizeof(IrtHmgnMatType)); /* Here some useful parameters to play with in tesselating freeforms: */ CGSkelFFCState.FineNess = polygonFineness; /* Res. of tesselation, larger is finer. */ CGSkelFFCState.ComputeUV = TRUE; /* Wants UV coordinates for textures. */ CGSkelFFCState.FourPerFlat = TRUE;/* 4 poly per ~flat patch, 2 otherwise.*/ CGSkelFFCState.LinearOnePolyFlag = TRUE; /* Linear srf gen. one poly. */ /* Traverse ALL the parsed data, recursively. */ IPTraverseObjListHierarchy(PObjects, CrntViewMat, CGSkelDumpOneTraversedObject); // Convert to our data structure: outObjects = IritAdapter::Convert(PObjects); // Finished converting return true; }
/***************************************************************************** * DESCRIPTION: M * Main module of irit2xfg - Read command line and do what is needed... M * * * PARAMETERS: M * argc, argv: Command line. M * * * RETURN VALUE: M * int: Return code. M * * * KEYWORDS: M * main M *****************************************************************************/ int main(int argc, char **argv) { int Error, HasTime = FALSE, PrintSizeFlag = FALSE, NumOfIsolinesFlag = FALSE, CrvOptimalPolyFlag = FALSE, SrfOptimalPolyFlag = FALSE, VerFlag = FALSE, OutFileFlag = FALSE, TranslateFlag = FALSE, NumFiles = 0; char *StrNumOfIsolines = NULL, **FileNames = NULL; IrtRType CurrentTime; IPObjectStruct *PObjects; IrtHmgnMatType CrntViewMat; #ifdef DEBUG_IRIT_MALLOC IritInitTestDynMemory(); #endif /* DEBUG_IRIT_MALLOC */ if ((Error = GAGetArgs (argc, argv, CtrlStr, &PrintSizeFlag, &GlblPrintSize, &TranslateFlag, &GlblXTranslate, &GlblYTranslate, &NumOfIsolinesFlag, &StrNumOfIsolines, &CrvOptimalPolyFlag, &IPFFCState.CrvApproxMethod, &IPFFCState.CrvApproxTolSamples, &SrfOptimalPolyFlag, &IPFFCState.OptimalPolygons, &IPFFCState.FineNess, &IPFFCState.DrawFFMesh, &IPFFCState.DrawFFGeom, &IPFFCState.Talkative, &HasTime, &CurrentTime, &IPFFCState.ShowInternal, &OutFileFlag, &OutFileName, &VerFlag, &NumFiles, &FileNames)) != 0) { GAPrintErrMsg(Error); GAPrintHowTo(CtrlStr); Irit2XfgExit(1); } if (VerFlag) { IRIT_INFO_MSG_PRINTF("\n%s\n\n", VersionStr); GAPrintHowTo(CtrlStr); Irit2XfgExit(0); } if (!NumFiles) { IRIT_WARNING_MSG("No data file names were given, exit.\n"); GAPrintHowTo(CtrlStr); Irit2XfgExit(1); } IPFFCState.DumpObjsAsPolylines = !SrfOptimalPolyFlag; IPFFCState.ComputeNrml = FALSE; /* No need for normals of vertices. */ if (NumOfIsolinesFlag && StrNumOfIsolines != NULL) { if (sscanf(StrNumOfIsolines, "%d:%d:%d", &IPFFCState.NumOfIsolines[0], &IPFFCState.NumOfIsolines[1], &IPFFCState.NumOfIsolines[2]) != 3) { if (sscanf(StrNumOfIsolines, "%d:%d", &IPFFCState.NumOfIsolines[0], &IPFFCState.NumOfIsolines[1]) != 2) { if (sscanf(StrNumOfIsolines, "%d", &IPFFCState.NumOfIsolines[1]) != 1) { IRIT_WARNING_MSG( "Number(s) of isolines (-I) cannot be parsed.\n"); GAPrintHowTo(CtrlStr); Irit2XfgExit(1); } else { IPFFCState.NumOfIsolines[2] = IPFFCState.NumOfIsolines[1] = IPFFCState.NumOfIsolines[0]; } } else { IPFFCState.NumOfIsolines[2] = IPFFCState.NumOfIsolines[0]; } } } /* Get the data files: */ IPSetFlattenObjects(FALSE); if ((PObjects = IPGetDataFiles((const char **) FileNames, NumFiles, TRUE, FALSE)) == NULL) Irit2XfgExit(1); PObjects = IPResolveInstances(PObjects); if (HasTime) GMAnimEvalAnimationList(CurrentTime, PObjects); else GMAnimEvalAnimationList(GM_ANIM_NO_DEFAULT_TIME, PObjects); if (IPWasPrspMat) MatMultTwo4by4(CrntViewMat, IPViewMat, IPPrspMat); else IRIT_GEN_COPY(CrntViewMat, IPViewMat, sizeof(IrtHmgnMatType)); IPTraverseObjListHierarchy(PObjects, CrntViewMat, IPMapObjectInPlace); DumpDataForFIG(OutFileFlag ? OutFileName : NULL, PObjects); Irit2XfgExit(0); return 0; }
/***************************************************************************** * DESCRIPTION: M * This function is a variation BspSrfInterpScatPts function that is less M * accurate/stable but is faster. M * The difference is that we solve a LSQ problem as A'*A*Vertices=A'*points M * where A' is the transpose matrix of A. M * This method is also refered to as pseudo inverse. M * The SVD decomposition is still used to calculate the above equation set. M * Given a set of scattered points, PtList, the function computes a Bspline M * surface of order UOrder by VOrder that interpolates or least square M * approximates the M given set of scattered points. M * PtList is a NULL terminated lists of CagdPtStruct structs, with each M * point holding (u, v, x [, y[, z]]). That is, E3 points create an E1 M * scalar surface and E5 points create an E3 surface, M * * * PARAMETERS: M * PtList: A NULL terminating array of linked list of points. M * UOrder: Of the to be created surface. M * VOrder: Of the to be created surface. M * USize: U size of the to be created surface. M * VSize: V size of the to be created surface. M * UKV: Expected knot vector in U direction, NULL for uniform open. M * VKV: Expected knot vector in V direction, NULL for uniform open. M * MatrixCondition: address of a IrtRType to return SVD matrix M * condition number to. if NULL, this option is ignored M * * * RETURN VALUE: M * CagdSrfStruct *: Constructed interpolating/approximating surface. M * * * KEYWORDS: M * BspSrfInterpScatPts2, interpolation, least square approximation M *****************************************************************************/ CagdSrfStruct *BspSrfInterpScatPts2(const CagdCtlPtStruct *PtList, int UOrder, int VOrder, int USize, int VSize, CagdRType *UKV, CagdRType *VKV, CagdRType *MatrixCondition) { int Row, i, j, NumCoords = CAGD_NUM_OF_PT_COORD(PtList -> PtType), PtListLen = CagdListLength(PtList), Size = USize * VSize; CagdBType NewUKV = FALSE, NewVKV = FALSE; CagdRType *MultMat, TempMatConditionNumber, *R, *P, *InterpPts, *RightSide, *ULine = (CagdRType *) IritMalloc(sizeof(CagdRType) * UOrder); CagdSparseMatStruct *Mat, *MatTranspose; CagdSparseCellStruct *SparseCell; const CagdCtlPtStruct *Pt; CagdSrfStruct *Srf; Mat = CagdSparseMatNew(IRIT_MAX(Size, PtListLen),Size,TRUE); if (NumCoords < 3) { CAGD_FATAL_ERROR(CAGD_ERR_PT_OR_LEN_MISMATCH); return NULL; } if (UKV == NULL) { UKV = BspKnotUniformOpen(USize, UOrder, NULL); BspKnotAffineTrans2(UKV, USize + UOrder, 0.0, 1.0); NewUKV = TRUE; } if (VKV == NULL) { VKV = BspKnotUniformOpen(VSize, VOrder, NULL); BspKnotAffineTrans2(VKV, VSize + VOrder, 0.0, 1.0); NewVKV = TRUE; } for (Pt = PtList, Row = 0; Pt != NULL; Pt = Pt -> Pnext, Row++) { int UIndex, VIndex; CagdRType *VLine; if (NumCoords != CAGD_NUM_OF_PT_COORD(Pt -> PtType)) { CAGD_FATAL_ERROR(CAGD_ERR_PT_OR_LEN_MISMATCH); IritFree(ULine); IritFree(Mat); return NULL; } VLine = BspCrvCoxDeBoorBasis(UKV, UOrder, USize, FALSE, Pt -> Coords[1], &UIndex); IRIT_GEN_COPY(ULine, VLine, sizeof(CagdRType) * UOrder); VLine = BspCrvCoxDeBoorBasis(VKV, VOrder, VSize, FALSE, Pt -> Coords[2], &VIndex); for (j = VIndex; j < VIndex + VOrder; j++) for (i = UIndex; i < UIndex + UOrder; i++) CagdSparseMatNewCell(Mat, Row, (j * USize + i), ULine[i - UIndex] * VLine[j - VIndex]); } IritFree(ULine); /* The LSQ problem may be solved using the following equation: */ /* A' * A * V = A' * P, where, */ /* A - the matrix previously calculated */ /* A' - is the tranpost of A */ /* V - vertices */ /* P - points to approximate */ /* Calculate the tranpose matrix. */ MatTranspose=CagdSparseMatTranspose(Mat, FALSE); /* Solve for the coefficients of all the coordinates of the curve. */ InterpPts = (CagdRType *) IritMalloc(sizeof(CagdRType) * PtListLen); /* Calculate the right side of the equation. */ /* Allocate Size * 3 (for easch component x, y, x). */ RightSide = (CagdRType *) IritMalloc(sizeof(CagdRType) * Size * 3); P = RightSide; /* Multiply A' * points and save result in vector for a later use. */ for (i = 3; i <= NumCoords; i++) { for (Pt = PtList, R = InterpPts; Pt != NULL; Pt = Pt -> Pnext) *R++ = Pt -> Coords[i]; for (j = 0; j < Size; j++, P++){ SparseCell = MatTranspose->RowStart[j]; *P = 0.0; while (SparseCell != NULL) { *P += SparseCell -> CellValue * InterpPts[SparseCell->CellCol]; SparseCell = SparseCell -> NextCol; } } } IritFree(InterpPts); /* Calculate A' * A. */ MultMat = CagdSparseMatMultNonSparseResult(MatTranspose,Mat); /* We don't need them anymore. */ CagdSparseMatFree(Mat); CagdSparseMatFree(MatTranspose); /* Compute SVD decomposition for Mat. */ TempMatConditionNumber = IRIT_FABS(SvdLeastSqr(MultMat, NULL, NULL, Size, Size)); /* Return the matrix condition number. */ if (MatrixCondition != NULL) *MatrixCondition = TempMatConditionNumber; if (TempMatConditionNumber < IRIT_UEPS && Size <= PtListLen) { CAGD_FATAL_ERROR(CAGD_ERR_NO_SOLUTION); IritFree(MultMat); return NULL; } IritFree(MultMat); /* Construct the Bspline surface and copy its knot vectors. */ Srf = BspSrfNew(USize, VSize, UOrder, VOrder, CAGD_MAKE_PT_TYPE(FALSE, NumCoords - 2)); CAGD_GEN_COPY(Srf -> UKnotVector, UKV, (CAGD_SRF_UPT_LST_LEN(Srf) + UOrder) * sizeof(CagdRType)); CAGD_GEN_COPY(Srf -> VKnotVector, VKV, (CAGD_SRF_VPT_LST_LEN(Srf) + VOrder) * sizeof(CagdRType)); for ( i = 0; i < NumCoords-2; i++){ SvdLeastSqr(NULL, Srf -> Points[i+1], RightSide+(i*Size), Size, Size); } IritFree(RightSide); if (NewUKV) IritFree(UKV); if (NewVKV) IritFree(VKV); return Srf; }
/***************************************************************************** * DESCRIPTION: M * Given a set of scattered points, PtList, computes a Bspline surface of M * order UOrder by VOrder that interpolates or least square approximates the M * given set of scattered points. M * PtList is a NULL terminated lists of CagdPtStruct structs, with each M * point holding (u, v, x [, y[, z]]). That is, E3 points create an E1 M * scalar surface and E5 points create an E3 surface, M * * * PARAMETERS: M * PtList: A NULL terminating array of linked list of points. M * UOrder: Of the to be created surface. M * VOrder: Of the to be created surface. M * USize: U size of the to be created surface. M * VSize: V size of the to be created surface. M * UKV: Expected knot vector in U direction, NULL for uniform open. M * VKV: Expected knot vector in V direction, NULL for uniform open. M * * * RETURN VALUE: M * CagdSrfStruct *: Constructed interpolating/approximating surface. M * * * KEYWORDS: M * BspSrfInterpScatPts, interpolation, least square approximation M *****************************************************************************/ CagdSrfStruct *BspSrfInterpScatPts(const CagdCtlPtStruct *PtList, int UOrder, int VOrder, int USize, int VSize, CagdRType *UKV, CagdRType *VKV) { int i, j, NumCoords = CAGD_NUM_OF_PT_COORD(PtList -> PtType), PtListLen = CagdListLength(PtList), Size = USize * VSize; CagdBType NewUKV = FALSE, NewVKV = FALSE; CagdRType *M, *R, *InterpPts, *ULine = (CagdRType *) IritMalloc(sizeof(CagdRType) * UOrder), *Mat = (CagdRType *) IritMalloc(sizeof(CagdRType) * Size * IRIT_MAX(Size, PtListLen)); const CagdCtlPtStruct *Pt; CagdSrfStruct *Srf; if (NumCoords < 3) { CAGD_FATAL_ERROR(CAGD_ERR_PT_OR_LEN_MISMATCH); return NULL; } IRIT_ZAP_MEM(Mat, sizeof(CagdRType) * Size * IRIT_MAX(Size, PtListLen)); if (UKV == NULL) { UKV = BspKnotUniformOpen(USize, UOrder, NULL); BspKnotAffineTrans2(UKV, USize + UOrder, 0.0, 1.0); NewUKV = TRUE; } if (VKV == NULL) { VKV = BspKnotUniformOpen(VSize, VOrder, NULL); BspKnotAffineTrans2(VKV, VSize + VOrder, 0.0, 1.0); NewVKV = TRUE; } for (Pt = PtList, M = Mat; Pt != NULL; Pt = Pt -> Pnext, M += Size) { int UIndex, VIndex; CagdRType *VLine; if (NumCoords != CAGD_NUM_OF_PT_COORD(Pt -> PtType)) { CAGD_FATAL_ERROR(CAGD_ERR_PT_OR_LEN_MISMATCH); IritFree(ULine); IritFree(Mat); return NULL; } VLine = BspCrvCoxDeBoorBasis(UKV, UOrder, USize, FALSE, Pt -> Coords[1], &UIndex); IRIT_GEN_COPY(ULine, VLine, sizeof(CagdRType) * UOrder); VLine = BspCrvCoxDeBoorBasis(VKV, VOrder, VSize, FALSE, Pt -> Coords[2], &VIndex); for (j = VIndex; j < VIndex + VOrder; j++) for (i = UIndex; i < UIndex + UOrder; i++) M[j * USize + i] = ULine[i - UIndex] * VLine[j - VIndex]; } IritFree(ULine); # ifdef DEBUG { IRIT_SET_IF_DEBUG_ON_PARAMETER(_DebugPrintInputSvd, FALSE) { for (i = 0; i < PtListLen; i++) { IRIT_INFO_MSG("["); for (j = 0; j < Size; j++) { IRIT_INFO_MSG_PRINTF("%7.4f ", Mat[i * Size + j]); } IRIT_INFO_MSG("]\n"); } } } # endif /* DEBUG */ /* Compute SVD decomposition for Mat. */ if (IRIT_FABS(SvdLeastSqr(Mat, NULL, NULL, IRIT_MAX(Size, PtListLen), Size)) < IRIT_UEPS && Size <= PtListLen) { CAGD_FATAL_ERROR(CAGD_ERR_NO_SOLUTION); IritFree(Mat); return NULL; } IritFree(Mat); /* Construct the Bspline surface and copy its knot vectors. */ Srf = BspSrfNew(USize, VSize, UOrder, VOrder, CAGD_MAKE_PT_TYPE(FALSE, NumCoords - 2)); CAGD_GEN_COPY(Srf -> UKnotVector, UKV, (CAGD_SRF_UPT_LST_LEN(Srf) + UOrder) * sizeof(CagdRType)); CAGD_GEN_COPY(Srf -> VKnotVector, VKV, (CAGD_SRF_VPT_LST_LEN(Srf) + VOrder) * sizeof(CagdRType)); /* Solve for the coefficients of all the coordinates of the curve. */ InterpPts = (CagdRType *) IritMalloc(sizeof(CagdRType) * IRIT_MAX(Size, PtListLen)); for (i = 3; i <= NumCoords; i++) { for (Pt = PtList, R = InterpPts; Pt != NULL; Pt = Pt -> Pnext) *R++ = Pt -> Coords[i]; SvdLeastSqr(NULL, Srf -> Points[i - 2], InterpPts, PtListLen, Size); } SvdLeastSqr(NULL, NULL, NULL, 0, 0); /* Clean up. */ IritFree(InterpPts); if (NewUKV) IritFree(UKV); if (NewVKV) IritFree(VKV); return Srf; }