/****************************************************************************** * Mvar_Rev.c - Reverses, promotes, and project multivariates. * ******************************************************************************* * (C) Gershon Elber, Technion, Israel Institute of Technology * ******************************************************************************* * Written by Gershon Elber, June. 97. * ******************************************************************************/ #include #include #include #include "mvar_loc.h" /***************************************************************************** * DESCRIPTION: M * Reverse the role of the given two axis by flipping them out. M * * * PARAMETERS: M * MV: Multi-Variate to reverse. M * Axis1, Axis2: Two axis to flip over. M * * * RETURN VALUE: M * MvarMVStruct *: Reversed multi-variate. M * * * SEE ALSO: M * MvarPromoteMVToMV, MvarMVShiftAxes M * * * KEYWORDS: M * MvarMVReverse, multi-variates M *****************************************************************************/ MvarMVStruct *MvarMVReverse(MvarMVStruct *MV, int Axis1, int Axis2) { CagdBType IsNotRational = !MVAR_IS_RATIONAL_MV(MV); MvarMVStruct *MVRev; CagdRType **Points, **RevPoints; int i, *Indices, Index, MaxCoord = CAGD_NUM_OF_PT_COORD(MV -> PType); if (Axis1 == Axis2) return MvarMVCopy(MV); if (Axis1 < 0 || Axis1 >= MV -> Dim || Axis2 < 0 || Axis2 >= MV -> Dim) { MVAR_FATAL_ERROR(MVAR_ERR_INVALID_AXIS); return NULL; } /* Duplicate the multivariate and flip all relevant material. */ MVRev = MvarMVCopy(MV); SWAP(int, MVRev -> Lengths[Axis1], MVRev -> Lengths[Axis2]); SWAP(int, MVRev -> Orders[Axis1], MVRev -> Orders[Axis2]); SWAP(int, MVRev -> Periodic[Axis1], MVRev -> Periodic[Axis2]); SWAP(CagdRType *, MVRev -> KnotVectors[Axis1], MVRev -> KnotVectors[Axis2]); for (i = 0; i < MVRev -> Dim; i++) MVRev -> SubSpaces[i] = i == 0 ? 1 : MVRev -> SubSpaces[i - 1] * MVRev -> Lengths[i - 1]; Indices = (int *) IritMalloc(sizeof(int) * MV -> Dim); ZAP_MEM(Indices, sizeof(int) * MV -> Dim); Index = 0; Points = MV -> Points; RevPoints = MVRev -> Points; do { int RevIndex; SWAP(int, Indices[Axis1], Indices[Axis2]); RevIndex = MvarGetPointsMeshIndices(MVRev, Indices); SWAP(int, Indices[Axis1], Indices[Axis2]); for (i = IsNotRational; i <= MaxCoord; i++) RevPoints[i][RevIndex] = Points[i][Index]; } while (MvarIncrementMeshIndices2(MV, Indices, &Index)); IritFree(Indices); return MVRev; } /***************************************************************************** * DESCRIPTION: M * Shift the last index in, instead of index Axis. All axes after Axis are M * shifted forward one location as we.l. M * * * PARAMETERS: M * MV: Multi-Variate to shift axes. M * Axis: From where to shift forward until last Axis and put last Axis M * Here instead. M * * * RETURN VALUE: M * MvarMVStruct *: Multi-variate, with shifted axes M * * * SEE ALSO: M * MvarMVReverse, MvarPromoteMVToMV M * * * KEYWORDS: M * MvarMVShiftAxes, multi-variates M *****************************************************************************/ MvarMVStruct *MvarMVShiftAxes(MvarMVStruct *MV, int Axis) { CagdBType IsNotRational = !MVAR_IS_RATIONAL_MV(MV); MvarMVStruct *MVRev; CagdRType *SaveKV, **Points, **RevPoints; int i, SaveIndex, *Indices, Index, Dim = MV -> Dim, MaxCoord = CAGD_NUM_OF_PT_COORD(MV -> PType); if (Axis == Dim - 1) return MvarMVCopy(MV); if (Axis < 0 || Axis >= Dim) { MVAR_FATAL_ERROR(MVAR_ERR_INVALID_AXIS); return NULL; } /* Duplicate the multivariate and flip all relevant material. */ MVRev = MvarMVCopy(MV); SaveIndex = MVRev -> Lengths[Dim - 1]; for (i = Dim - 1; i > Axis; i--) MVRev -> Lengths[i] = MVRev -> Lengths[i - 1]; MVRev -> Lengths[Axis] = SaveIndex; SaveIndex = MVRev -> Orders[Dim - 1]; for (i = Dim - 1; i > Axis; i--) MVRev -> Orders[i] = MVRev -> Orders[i - 1]; MVRev -> Orders[Axis] = SaveIndex; SaveIndex = MVRev -> Periodic[Dim - 1]; for (i = Dim - 1; i > Axis; i--) MVRev -> Periodic[i] = MVRev -> Periodic[i - 1]; MVRev -> Periodic[Axis] = SaveIndex; SaveKV = MVRev -> KnotVectors[Dim - 1]; for (i = Dim - 1; i > Axis; i--) MVRev -> KnotVectors[i] = MVRev -> KnotVectors[i - 1]; MVRev -> KnotVectors[Axis] = SaveKV; for (i = 0; i < MVRev -> Dim; i++) MVRev -> SubSpaces[i] = i == 0 ? 1 : MVRev -> SubSpaces[i - 1] * MVRev -> Lengths[i - 1]; Indices = (int *) IritMalloc(sizeof(int) * MV -> Dim); ZAP_MEM(Indices, sizeof(int) * MV -> Dim); Index = 0; Points = MV -> Points; RevPoints = MVRev -> Points; do { int RevIndex; /* Shift the indices from Axis to Dim-1. */ SaveIndex = Indices[Dim - 1]; for (i = Dim - 1; i > Axis; i--) Indices[i] = Indices[i - 1]; Indices[Axis] = SaveIndex; RevIndex = MvarGetPointsMeshIndices(MVRev, Indices); /* Shift the indices back from Axis to Dim-1. */ SaveIndex = Indices[Axis]; for (i = Axis; i < Dim - 1; i++) Indices[i] = Indices[i + 1]; Indices[Dim - 1] = SaveIndex; /* Copy the control point. */ for (i = IsNotRational; i <= MaxCoord; i++) RevPoints[i][RevIndex] = Points[i][Index]; } while (MvarIncrementMeshIndices2(MV, Indices, &Index)); IritFree(Indices); return MVRev; } /***************************************************************************** * DESCRIPTION: M * Increase by one the dimensionality of the given multivariate, by M * introducing a new constant (degree zero) axis with one control point in M * direction Axis. M * * * PARAMETERS: M * MV: Multi-Variate to promote. M * Axis: Axis of promotion. Between zero and MV -> Dim. M * * * RETURN VALUE: M * MvarMVStruct *: Promoted multi-variate. M * * * SEE ALSO: M * MvarMVShiftAxes, MvarMVFromMV, MvarPromoteMVToMV2 M * * * KEYWORDS: M * MvarPromoteMVToMV, multi-variates M *****************************************************************************/ MvarMVStruct *MvarPromoteMVToMV(MvarMVStruct *MV, int Axis) { MvarMVStruct *ProMV; if (Axis < 0 || Axis > MV -> Dim) { MVAR_FATAL_ERROR(MVAR_ERR_INVALID_AXIS); return NULL; } ProMV = MvarMVFromMV(MV, 0.0, -1); if (Axis != ProMV -> Dim - 1) { MvarMVStruct *ProMV2 = MvarMVShiftAxes(ProMV, Axis); MvarMVFree(ProMV); ProMV = ProMV2; } return ProMV; } /***************************************************************************** * DESCRIPTION: M * Increase by the dimensionality of the given multivariate to NewDim, by M * introducing new constant (degree zero) axes with one control points in all M * new directions. M * The Axis of the original MV will be starting at StartAxis. M * * * PARAMETERS: M * MV: Multi-Variate to promote. M * NewDim: New dimension of the promoted multivariate. M * StartAxis: Original MV would span axes StartAxis to StartAxis+MV->Dim-1. M * * * RETURN VALUE: M * MvarMVStruct *: Promoted multi-variate. M * * * SEE ALSO: M * MvarMVShiftAxes, MvarMVFromMV, MvarPromoteMVToMV M * * * KEYWORDS: M * MvarPromoteMVToMV2, multi-variates M *****************************************************************************/ MvarMVStruct *MvarPromoteMVToMV2(MvarMVStruct *MV, int NewDim, int StartAxis) { int i; MvarMVStruct *MVTmp2, *MVTmp1 = MV; if (StartAxis + MV -> Dim > NewDim) { MVAR_FATAL_ERROR(MVAR_ERR_INVALID_AXIS); return NULL; } for (i = 0; i < StartAxis; i++) { MVTmp2 = MvarPromoteMVToMV(MVTmp1, 0); if (MVTmp1 != MV) MvarMVFree(MVTmp1); MVTmp1 = MVTmp2; } for (i = MVTmp1 -> Dim; i < NewDim; i++) { MVTmp2 = MvarPromoteMVToMV(MVTmp1, MVTmp1 -> Dim); if (MVTmp1 != MV) MvarMVFree(MVTmp1); MVTmp1 = MVTmp2; } return MVTmp1; }