mirror of
https://github.com/openmoh/openmohaa.git
synced 2025-04-29 06:07:57 +03:00
280 lines
6.4 KiB
C++
280 lines
6.4 KiB
C++
/*
|
|
===========================================================================
|
|
Copyright (C) 2015 the OpenMoHAA team
|
|
|
|
This file is part of OpenMoHAA source code.
|
|
|
|
OpenMoHAA source code is free software; you can redistribute it
|
|
and/or modify it under the terms of the GNU General Public License as
|
|
published by the Free Software Foundation; either version 2 of the License,
|
|
or (at your option) any later version.
|
|
|
|
OpenMoHAA source code is distributed in the hope that it will be
|
|
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with OpenMoHAA source code; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
===========================================================================
|
|
*/
|
|
|
|
// spline.h: Spline paths.
|
|
//
|
|
|
|
#pragma once
|
|
|
|
#include "g_local.h"
|
|
#include <class.h>
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
class cSpline : public Class
|
|
{
|
|
public:
|
|
int m_iPoints;
|
|
float m_vPoints[cPoints][cGrids];
|
|
int m_iPointFlags[cPoints];
|
|
|
|
cSpline();
|
|
|
|
void Reset(void);
|
|
int Add(float *fAdd, int flags);
|
|
void Modify(int, float *, int);
|
|
void UniformAdd(float *pos);
|
|
void Remove(class cSpline<cGrids, cPoints> *, int);
|
|
void RemoveRange(int, int);
|
|
int Right(float x);
|
|
float *Get(float x, int *flags);
|
|
float *GetByNode(float x, int *flags);
|
|
int Append(cSpline<cGrids, cPoints> *pNew);
|
|
|
|
void Archive(Archiver& arc);
|
|
};
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
cSpline<cGrids, cPoints>::cSpline()
|
|
{
|
|
m_iPoints = 0;
|
|
}
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
void cSpline<cGrids, cPoints>::Archive(Archiver& arc)
|
|
{
|
|
arc.ArchiveInteger(&m_iPoints);
|
|
|
|
for (int i = 0; i < cPoints; i++) {
|
|
for (int j = 0; j < cGrids; j++) {
|
|
arc.ArchiveFloat(&m_vPoints[i][j]);
|
|
}
|
|
|
|
arc.ArchiveInteger(&m_iPointFlags[i]);
|
|
}
|
|
}
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
void cSpline<cGrids, cPoints>::Reset(void)
|
|
{
|
|
m_iPoints = 0;
|
|
}
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
int cSpline<cGrids, cPoints>::Add(float *fAdd, int flags)
|
|
{
|
|
int i;
|
|
int ii;
|
|
int insertIndex;
|
|
|
|
if (m_iPoints + 1 > cPoints) {
|
|
return -1;
|
|
}
|
|
|
|
insertIndex = Right(*fAdd);
|
|
|
|
for (i = m_iPoints; i > insertIndex; i--) {
|
|
for (ii = 0; ii < cGrids; ii++) {
|
|
m_vPoints[i][ii] = m_vPoints[i - 1][ii];
|
|
}
|
|
|
|
m_iPointFlags[i] = m_iPointFlags[i - 1];
|
|
}
|
|
|
|
for (i = 0; i < cGrids; i++) {
|
|
m_vPoints[insertIndex][i] = fAdd[i];
|
|
}
|
|
|
|
m_iPointFlags[insertIndex] = flags;
|
|
m_iPoints++;
|
|
|
|
return insertIndex;
|
|
}
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
void cSpline<cGrids, cPoints>::UniformAdd(float *pos)
|
|
{
|
|
int i;
|
|
int ii;
|
|
|
|
for (i = 0; i < m_iPoints; i++) {
|
|
for (ii = 0; ii < cGrids; ii++) {
|
|
m_vPoints[i][ii] += pos[ii];
|
|
}
|
|
}
|
|
}
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
int cSpline<cGrids, cPoints>::Right(float x)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < m_iPoints; i++) {
|
|
if (m_vPoints[i][0] > x) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
float *cSpline<cGrids, cPoints>::Get(float x, int *flags)
|
|
{
|
|
if (!m_iPoints) {
|
|
return NULL;
|
|
}
|
|
|
|
int rp;
|
|
int i;
|
|
static float r[cGrids];
|
|
double delta[cGrids];
|
|
|
|
rp = Right(x);
|
|
|
|
if (rp) {
|
|
if (rp == m_iPoints) {
|
|
if (flags) {
|
|
*flags = m_iPointFlags[rp - 1];
|
|
}
|
|
|
|
for (i = 0; i < cGrids; i++) {
|
|
r[i] = m_vPoints[rp - 1][i];
|
|
}
|
|
} else {
|
|
if (flags) {
|
|
*flags = m_iPointFlags[rp - 1];
|
|
}
|
|
|
|
for (i = 0; i < cGrids; i++) {
|
|
delta[i] = m_vPoints[rp][i] - m_vPoints[rp - 1][i];
|
|
}
|
|
|
|
for (i = 0; i < cGrids; i++) {
|
|
r[i] = (x - m_vPoints[rp - 1][0]) / delta[0] * delta[i] + m_vPoints[rp - 1][i];
|
|
}
|
|
}
|
|
} else {
|
|
if (flags) {
|
|
*flags = m_iPointFlags[0];
|
|
}
|
|
|
|
for (i = 0; i < cGrids; i++) {
|
|
r[i] = m_vPoints[0][i];
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
float *cSpline<cGrids, cPoints>::GetByNode(float x, int *flags)
|
|
{
|
|
if (!m_iPoints) {
|
|
return NULL;
|
|
}
|
|
|
|
int rp;
|
|
int i;
|
|
static float r[cGrids];
|
|
double delta[cGrids];
|
|
|
|
rp = (int)(floor(x) + 1.0);
|
|
|
|
if (rp <= 0) {
|
|
if (flags) {
|
|
*flags = m_iPointFlags[0];
|
|
}
|
|
|
|
for (i = 0; i < cGrids; i++) {
|
|
r[i] = m_vPoints[0][i];
|
|
}
|
|
} else if (rp < m_iPoints) {
|
|
if (flags) {
|
|
*flags = m_iPointFlags[rp - 1];
|
|
}
|
|
|
|
for (i = 0; i < cGrids; i++) {
|
|
delta[i] = m_vPoints[rp][i] - m_vPoints[rp - 1][i];
|
|
}
|
|
|
|
for (i = 0; i < cGrids; i++) {
|
|
r[i] = (x - (rp - 1)) * delta[i] + m_vPoints[rp - 1][i];
|
|
}
|
|
} else {
|
|
if (flags) {
|
|
*flags = m_iPointFlags[m_iPoints - 1];
|
|
}
|
|
|
|
for (i = 0; i < cGrids; i++) {
|
|
r[i] = m_vPoints[m_iPoints - 1][i];
|
|
}
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
template<unsigned int cGrids, unsigned int cPoints>
|
|
int cSpline<cGrids, cPoints>::Append(cSpline<cGrids, cPoints> *pNew)
|
|
{
|
|
float *i_fTmp;
|
|
float o_fTmp[4];
|
|
float fIndexAdd;
|
|
int i;
|
|
int ii;
|
|
int iFlags = 0;
|
|
|
|
if (!pNew || pNew->m_iPoints == 0) {
|
|
return -1;
|
|
}
|
|
|
|
if (m_iPoints) {
|
|
int points;
|
|
|
|
points = m_iPoints;
|
|
fIndexAdd = *GetByNode(m_iPoints, NULL);
|
|
|
|
for (i = 0; i < pNew->m_iPoints; i++) {
|
|
i_fTmp = pNew->GetByNode(i, &iFlags);
|
|
|
|
for (ii = 0; ii < cGrids; ii++) {
|
|
o_fTmp[ii] = i_fTmp[ii];
|
|
}
|
|
|
|
o_fTmp[0] += fIndexAdd;
|
|
Add(o_fTmp, iFlags);
|
|
}
|
|
|
|
return points;
|
|
} else {
|
|
for (i = 0; i < pNew->m_iPoints; i++) {
|
|
i_fTmp = pNew->GetByNode(i, &iFlags);
|
|
|
|
for (ii = 0; ii < cGrids; ii++) {
|
|
o_fTmp[ii] = i_fTmp[ii];
|
|
}
|
|
|
|
Add(o_fTmp, iFlags);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
}
|