RCS Computation Toolkit This repository provides C++ and Python tools for computing radar cross section (RCS) from surface currents or analytical models
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.
 
 
 
 
 

492 lines
10 KiB

// TRI3D.CC
// Member functions for classes tri3d
#include <iostream>
#include <fstream>
#include <iomanip>
#include <math.h>
#include "mesh3d.h"
#include "vtr.h"
using namespace std;
template <class T>
void ReArrange(int n, T **nd, int OPT)
{
int i, j;
T *tmp;
for (i = 0; i < n; i ++) {
for (j = (i + 1); j < n; j ++) {
if ((OPT == ASCENDING && (*nd[i]) > (*nd[j])) ||
(OPT == DECENDING && (*nd[i]) < (*nd[j]))) {
tmp = nd[i];
nd[i] = nd[j];
nd[j] = tmp;
}
}
}
}
// constructor for tri3d
tri3d::tri3d(void )
{
int i;
for (i = 0; i < 3; i ++) eg[i] = 0;
n = 1; // only one star per triangle for now
type = NONE;
done = 0;
orient = PORIENT;
}
// set up procedures for tri3d
void tri3d::SetTri(edge3d *eg0, edge3d *eg1, edge3d *eg2)
{
eg[0] = eg0;
eg[1] = eg1;
eg[2] = eg2;
}
void tri3d::ReArrange() {
node3d *nd[3];
nd[0] = eg[0]->GetNodePtr(0);
nd[1] = eg[0]->GetNodePtr(1);
if (eg[1]->GetNodePtr(0) != nd[0] &&
eg[1]->GetNodePtr(0) != nd[1])
nd[2] = eg[1]->GetNodePtr(0);
else
nd[2] = eg[1]->GetNodePtr(1);
ReArrangeNd(3, nd, ASCENDING);
int j;
edge3d *tmpEdge[3];
for (j = 0; j < 3; j ++) {
int j1 = (j + 1) % 3;
int j2 = (j + 2) % 3;
int k;
for (k = 0; k < 3; k ++) {
if (SameEdge(eg[k], nd[j1], nd[j2]))
tmpEdge[j] = eg[k];
}
}
eg[0] = tmpEdge[0];
eg[1] = tmpEdge[1];
eg[2] = tmpEdge[2];
}
void tri3d::SetN(int nn) {
if (n != nn) {
n = nn;
}
}
void tri3d::SetId(int nn, int idx)
{
if (nn >= 0 && nn < n) {
id = idx;
}
}
void tri3d::SetType(int typeNum) { type = typeNum; }
// get functions for tri3d
int tri3d::GetId(int nn) {
if (nn < 0 || nn >= n) return NOT_ID_YET;
return id;
}
int tri3d::GetType() { return type; }
node3d *tri3d::GetNodePtr(int nn)
{
if (nn < 0 || nn >= 3) return 0;
switch (nn) {
case 0: return eg[2]->GetNodePtr(0);
case 1: return eg[0]->GetNodePtr(0);
case 2: return eg[0]->GetNodePtr(1);
}
}
// overload operators
const tri3d &tri3d::operator=(const tri3d &right)
{
if (&right != this) {
int i;
for (i = 0; i < 3; i ++) eg[i] = right.eg[i];
n = right.n;
id = right.id;
type = right.type;
num = right.num;
}
}
int tri3d::operator==(const tri3d &right) const
{
if (eg[0] != right.eg[0]) return 0;
if (eg[1] != right.eg[1]) return 0;
if (eg[2] != right.eg[2]) return 0;
return 1;
}
int tri3d::operator>(const tri3d &right) const
{
int i;
for (i = 0; i < 3; i ++) {
if ((*(eg[i])) > (*(right.eg[i]))) return 1;
if ((*(eg[i])) < (*(right.eg[i]))) return 0;
}
return 0;
}
int tri3d::operator<(const tri3d &right) const
{
int i;
for (i = 0; i < 3; i ++) {
if ((*(eg[i])) > (*(right.eg[i]))) return 0;
if ((*(eg[i])) < (*(right.eg[i]))) return 1;
}
return 0;
}
int tri3d::operator>=(const tri3d &right) const
{
int i;
for (i = 0; i < 3; i ++) {
if ((*(eg[i])) > (*(right.eg[i]))) return 1;
if ((*(eg[i])) < (*(right.eg[i]))) return 0;
}
return 1;
}
int tri3d::operator<=(const tri3d &right) const
{
int i;
for (i = 0; i < 3; i ++) {
if ((*(eg[i])) > (*(right.eg[i]))) return 0;
if ((*(eg[i])) < (*(right.eg[i]))) return 1;
}
return 1;
}
void tri3d::ComputeNormal()
{
vtr avtr, bvtr, nvtr;
avtr.setvtr(eg[2]->GetX(), eg[2]->GetY(), eg[2]->GetZ());
bvtr.setvtr(eg[1]->GetX(), eg[1]->GetY(), eg[1]->GetZ());
nvtr = avtr * bvtr;
nvtr.unitvtr();
nx = nvtr.getx();
ny = nvtr.gety();
nz = nvtr.getz();
}
void tri3d::NormalReverse()
{
nx = -nx;
ny = -ny;
nz = -nz;
orient = NORIENT;
}
char tri3d::GetOrient() { return orient; }
void tri3d::GetValidEdges(int triEdge[])
{
int i;
for (i = 0; i < 3; i ++) {
if (eg[i]->GetTriNumber() == 1) triEdge[i] = 0;
else
triEdge[i] = 1;
}
}
void tri3d::ResetDone() { done = 0; }
void tri3d::SetDone() { done = 1; }
char tri3d::IsDone() { return done; }
edge3d* tri3d::GetEdgePtr(int nn)
{
if (nn < 0 || nn >= 3) return 0;
return eg[nn];
}
void tri3d::GetNormal(double *xn, double *yn, double *zn)
{
// // original
// (*xn) = (double)(nx);
// (*yn) = (double)(ny);
// (*zn) = (double)(nz);
//modified
ComputeNormal();
// quik and derty ( not general ) way to find direction.
vtr cv, normal;
double cx, cy, cz;
cx = eg[0]->GetNodePtr(0)->GetX();
cy = eg[0]->GetNodePtr(0)->GetY();
cz = eg[0]->GetNodePtr(0)->GetZ();
cv.setvtr(cx, cy, cz);
normal.setvtr(nx, ny, nz);
if (dotP(cv, normal) < 0.0) NormalReverse();
(*xn) = (double)(nx);
(*yn) = (double)(ny);
(*zn) = (double)(nz);
}
void tri3d::GetGradVtr(int nn, double *gx, double *gy, double *gz)
{
double area = Area(this);
if (nn < 0 || nn >= 3) {
(*gx) = (*gy) = (*gz) = 0.0;
return;
}
vtr nvtr, tvtr, gvtr;
tvtr.setvtr(eg[nn]->GetX(), eg[nn]->GetY(), eg[nn]->GetZ());
nvtr.setvtr((double)nx, (double)ny, (double)nz);
gvtr = nvtr * tvtr;
gvtr = gvtr * (1.0 / (2.0 * area));
node3d *pt0, *pt1;
pt1 = GetNodePtr(nn);
pt0 = eg[nn]->GetNodePtr(0);
tvtr.setvtr(pt1->GetX() - pt0->GetX(), pt1->GetY() - pt0->GetY(), pt1->GetZ() - pt0->GetZ());
if (dotP(gvtr, tvtr) < 0.0) {
(*gx) = -gvtr.getx();
(*gy) = -gvtr.gety();
(*gz) = -gvtr.getz();
} else {
(*gx) = gvtr.getx();
(*gy) = gvtr.gety();
(*gz) = gvtr.getz();
}
}
void tri3d::GetGradVtr(int nn, double area, double *gx, double *gy, double *gz)
{
if (nn < 0 || nn >= 3) {
(*gx) = (*gy) = (*gz) = 0.0;
return;
}
vtr nvtr, tvtr, gvtr;
tvtr.setvtr(eg[nn]->GetX(), eg[nn]->GetY(), eg[nn]->GetZ());
nvtr.setvtr((double)nx, (double)ny, (double)nz);
gvtr = nvtr * tvtr;
gvtr = gvtr * (1.0 / (2.0 * area));
node3d *pt0, *pt1;
pt1 = GetNodePtr(nn);
pt0 = eg[nn]->GetNodePtr(0);
tvtr.setvtr(pt1->GetX() - pt0->GetX(), pt1->GetY() - pt0->GetY(), pt1->GetZ() - pt0->GetZ());
if (dotP(gvtr, tvtr) < 0.0) {
(*gx) = -gvtr.getx();
(*gy) = -gvtr.gety();
(*gz) = -gvtr.getz();
} else {
(*gx) = gvtr.getx();
(*gy) = gvtr.gety();
(*gz) = gvtr.getz();
}
}
void tri3d::print()
{
cout << "NODES " << endl;
GetNodePtr(0)->print();
GetNodePtr(1)->print();
GetNodePtr(2)->print();
cout << "EDGES" << endl;
eg[0]->print();
eg[1]->print();
eg[2]->print();
cout << endl;
cout << "Normal: ( " << nx << ", " << ny << ", " << nz << " )" << endl;
cout << "Orientation ";
if (GetOrient() == 0) cout << " 0 " << endl;
else
if (GetOrient() == 1) cout << " 1 " << endl;
cout << "Unknown Number " << id << endl << endl;
}
double Area(tri3d *tt)
{
edge3d *eg0, *eg1;
eg0 = tt->GetEdgePtr(0);
eg1 = tt->GetEdgePtr(1);
vtr avtr(eg0->GetX(), eg0->GetY(), eg0->GetZ());
vtr bvtr(eg1->GetX(), eg1->GetY(), eg1->GetZ());
vtr nvtr = avtr * bvtr;
return 0.5 * nvtr.magnitude();
}
double Area(tri3d tt)
{
edge3d *eg0, *eg1;
eg0 = tt.GetEdgePtr(0);
eg1 = tt.GetEdgePtr(1);
vtr avtr(eg0->GetX(), eg0->GetY(), eg0->GetZ());
vtr bvtr(eg1->GetX(), eg1->GetY(), eg1->GetZ());
vtr nvtr = avtr * bvtr;
return 0.5 * nvtr.magnitude();
}
tri3d *GetNeighborTriPtr(tri3d *tt, int nn)
{
if (nn < 0 || nn >= 3) return 0;
edge3d *eg;
eg = tt->GetEdgePtr(nn);
int i;
for (i = 0; i < eg->GetTriNumber(); i ++) {
if (eg->GetTriPtr(i) != tt)
return eg->GetTriPtr(i);
}
return 0;
}
int NodeInTri(node3d *nd, tri3d *tt)
{
int i;
for (i = 0; i < 3; i ++) {
if (tt->GetNodePtr(i) == nd) return (i + 1);
}
return 0;
}
// GetCartesian takes as inputs tt (the triangle), (zeta0, zeta1, zeta2) the barycentric coordinates
// It returns the corresponding Cartesian coordinates (x, y, z) at the point.
void GetCartesian(tri3d *tt,
double zeta0, double zeta1, double zeta2,
double *x, double *y, double *z)
{
int i;
node3d *nd;
double zc[3];
zc[0] = zeta0;
zc[1] = zeta1;
zc[2] = zeta2;
(*x) = (*y) = (*z) = 0.0;
for (i = 0; i < 3; i ++) {
nd = tt->GetNodePtr(i);
(*x) += zc[i] * nd->GetX();
(*y) += zc[i] * nd->GetY();
(*z) += zc[i] * nd->GetZ();
}
}
// GetCartesian takes as inputs tt (the triangle), (zeta0, zeta1, zeta2) the barycentric coordinates
// It returns the corresponding Cartesian coordinates (x, y, z) at the point.
void GetCartesian(tri3d *tt,
double zc[],
double *x, double *y, double *z)
{
int i;
node3d *nd;
(*x) = (*y) = (*z) = 0.0;
for (i = 0; i < 3; i ++) {
nd = tt->GetNodePtr(i);
(*x) += zc[i] * nd->GetX();
(*y) += zc[i] * nd->GetY();
(*z) += zc[i] * nd->GetZ();
}
}
double Distance(tri3d *t1, tri3d *t2)
{
double x0, y0, z0;
double x1, y1, z1;
double Rmin = 1.0e30;
int i;
for (i = 0; i < 3; i ++) {
x0 = t1->GetNodePtr(i)->GetX();
y0 = t1->GetNodePtr(i)->GetY();
z0 = t1->GetNodePtr(i)->GetZ();
int j;
for (j = 0; j < 3; j ++) {
x1 = t2->GetNodePtr(j)->GetX();
y1 = t2->GetNodePtr(j)->GetY();
z1 = t2->GetNodePtr(j)->GetZ();
double dd = (x1 - x0) * (x1 - x0) + (y1 - y0) * ( y1 - y0) + (z1 - z0) * (z1 - z0);
if (dd < Rmin) Rmin = dd;
}
}
return sqrt(Rmin);
}
vtr DirectLine(node3d *nd0, node3d *nd1)
{
vtr vv(nd1->GetX() - nd0->GetX(),
nd1->GetY() - nd0->GetY(),
nd1->GetZ() - nd0->GetZ());
return vv;
}
void tri3d::ComputeCenter(double *x, double *y, double *z)
{
vtr L10 = DirectLine(GetNodePtr(1), GetNodePtr(0));
vtr L12 = DirectLine(GetNodePtr(1), GetNodePtr(2));
vtr L02 = DirectLine(GetNodePtr(0), GetNodePtr(2));
vtr nd = L10 - L12 * (dotP(L10, L12) / L12.magSquare());
double d = dotP(L10, L02) / dotP(nd, L02) * 0.5;
(*x) = 0.5 * (GetNodePtr(1)->GetX() + GetNodePtr(2)->GetX()) + d * nd.getx();
(*y) = 0.5 * (GetNodePtr(1)->GetY() + GetNodePtr(2)->GetY()) + d * nd.gety();
(*z) = 0.5 * (GetNodePtr(1)->GetZ() + GetNodePtr(2)->GetZ()) + d * nd.getz();
}
double tri3d::ComputeRadius()
{
double cx, cy, cz;
ComputeCenter(&cx, &cy, &cz);
return Distance(GetNodePtr(0), cx, cy, cz);
}
void tri3d::GetNormal(double *xn, double *yn, double *zn, vtr &center)
{
// // original
// (*xn) = (double)(nx);
// (*yn) = (double)(ny);
// (*zn) = (double)(nz);
// modified
ComputeNormal();
// quik and derty ( not general ) way to find direction.
vtr cv, normal;
double cx, cy, cz;
cx = eg[0]->GetNodePtr(0)->GetX() - center.getx();
cy = eg[0]->GetNodePtr(0)->GetY() - center.gety();
cz = eg[0]->GetNodePtr(0)->GetZ() - center.getz();
cv.setvtr(cx, cy, cz);
normal.setvtr(nx, ny, nz);
if (dotP(cv, normal) < 0.0) NormalReverse();
(*xn) = (double)(nx);
(*yn) = (double)(ny);
(*zn) = (double)(nz);
}