You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

215 lines
5.8 KiB

#pragma once
#include <ostream>
#include <cmath>
#include "TinyVector.h"
#include "Mathematics/NURBSCurve.h"
typedef TinyVector<double, 3> vec3d;
class MyCurve
{
public:
MyCurve()
: t_min(0.0), t_max(1.0), closed(false)
{
start_vertex_index = (size_t)-1;
end_vertex_index = (size_t)-1;
}
const bool &is_closed() const { return closed; }
bool &is_closed() { return closed; }
const double &get_t_min() const { return t_min; }
double &get_t_min() { return t_min; }
const double &get_t_max() const { return t_max; }
double &get_t_max() { return t_max; }
const size_t &get_start_vertex_index() const { return start_vertex_index; }
size_t &get_start_vertex_index() { return start_vertex_index; }
const size_t &get_end_vertex_index() const { return end_vertex_index; }
size_t &get_end_vertex_index() { return end_vertex_index; }
virtual vec3d GetPosition(double t) = 0;
//tangent
virtual vec3d GetTangent(double t)
{
//impl for all curves withiin this class, not normalized
return vec3d(0.0, 0.0, 0.0);
}
void write_obj_curve(std::ostream &out, size_t &vcounter, int div)
{
int denom = closed ? div : div - 1;
for (int i = 0; i < div; i++)
{
double t = t_min + i * (t_max - t_min) / denom;
out << "v " << GetPosition(t) << std::endl;
}
for (int i = 0; i < div - 1; i++)
out << "l " << i + vcounter << ' ' << i + vcounter + 1 << std::endl;
if (closed)
out << "l " << vcounter + div - 1 << ' ' << vcounter << std::endl;
vcounter += div;
}
void write_data_curve(std::ostream &out, int div)
{
out << "curve " << (closed ? "closed " : "open ") << div << std::endl;
int denom = closed ? div : div - 1;
for (int i = 0; i < div; i++)
{
double t = t_min + i * (t_max - t_min) / denom;
out << GetPosition(t) << std::endl;
}
}
//protected:
double t_min, t_max;
bool closed;
size_t start_vertex_index, end_vertex_index;
};
//////////////////////////////////////////////
class MyLine : public MyCurve
{
public:
MyLine(const vec3d &_start, const vec3d &_end)
: start(_start), end(_end)
{
this->closed = false;
this->t_min = 0;
this->t_max = 1;
}
vec3d GetPosition(double t)
{
return start + t * (end - start);
}
vec3d GetTangent(double t)
{
vec3d tang = end - start;
//tang.Normalize();
return tang;
}
protected:
vec3d start, end;
};
//////////////////////////////////////////////
class MyCircle : public MyCurve
{
public:
MyCircle(const vec3d &_loc, const vec3d &_dirx, const vec3d &_diry,
double _radius, double _t_min, double _t_max, bool _closed)
: loc(_loc), dirx(_dirx), diry(_diry), radius(_radius)
{
this->t_min = _t_min;
this->t_max = _t_max;
this->closed = _closed;
}
vec3d GetPosition(double t)
{
return loc + radius * (cos(t) * dirx + sin(t) * diry);
}
vec3d GetTangent(double t)
{
return (-sin(t) * dirx + cos(t) * diry) * radius;
}
protected:
vec3d loc, dirx, diry;
double radius;
};
//////////////////////////////////////////////
class MyEllipse : public MyCurve
{
public:
MyEllipse(const vec3d &_loc, const vec3d &_dirx, const vec3d &_diry,
double _x_radius, double _y_radius, double _t_min, double _t_max, bool _closed)
: loc(_loc), dirx(_dirx), diry(_diry), x_radius(_x_radius), y_radius(_y_radius)
{
this->t_min = _t_min;
this->t_max = _t_max;
this->closed = _closed;
}
vec3d GetPosition(double t)
{
return loc + x_radius * cos(t) * dirx + y_radius * sin(t) * diry;
}
vec3d GetTangent(double t)
{
return -x_radius * sin(t) * dirx + y_radius * cos(t) * diry;
}
protected:
vec3d loc, dirx, diry;
double x_radius, y_radius;
};
class MySplineCurve : public MyCurve
{
public:
MySplineCurve(
int degree,
const std::vector<gte::Vector<3, double>>& controls,
const std::vector<double>& myknots,
const std::vector<double>& myweights,
double _t_min, double _t_max, bool _closed)
{
this->t_min = _t_min;
this->t_max = _t_max;
this->closed = _closed;
gte::BasisFunctionInput<double> my_input;
my_input.degree = degree;
my_input.numControls = (int)controls.size();
//my_input.periodic = _closed;
my_input.periodic = false;
my_input.uniform = false;
std::vector<std::pair<double, int>> knots_stataus;
knots_stataus.push_back(std::make_pair(myknots[0], 1));
for (size_t i = 1; i < myknots.size(); i++)
{
if (myknots[i] == knots_stataus.back().first)
knots_stataus.back().second++;
else
knots_stataus.push_back(std::make_pair(myknots[i], 1));
}
my_input.numUniqueKnots = (int)knots_stataus.size();
my_input.uniqueKnots.resize(my_input.numUniqueKnots);
for (size_t i = 0; i < knots_stataus.size(); i++)
{
my_input.uniqueKnots[i].t = knots_stataus[i].first;
my_input.uniqueKnots[i].multiplicity = knots_stataus[i].second;
}
mycurve = new gte::NURBSCurve<3, double>(my_input, controls.data(), myweights.data());
}
~MySplineCurve()
{
if (mycurve)
delete mycurve;
}
vec3d GetPosition(double t)
{
gte::Vector<3, double> V = mycurve->GetPosition(t);
return vec3d(V[0], V[1], V[2]);
}
vec3d GetTangent(double t)
{
gte::Vector<3, double> V = mycurve->GetTangent(t);
return vec3d(V[0], V[1], V[2]);
}
protected:
gte::NURBSCurve<3, double>* mycurve;
};