mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Adding moment of inertia code, unused as yet.
This commit is contained in:
403
src/meshTools/momentOfInertia/momentOfInertia.C
Normal file
403
src/meshTools/momentOfInertia/momentOfInertia.C
Normal file
@ -0,0 +1,403 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2007-2009 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM 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.
|
||||
|
||||
OpenFOAM 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 OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
momentOfInertia
|
||||
|
||||
Description
|
||||
Reimplementation of volInt.c by Brian Mirtich.
|
||||
* mirtich@cs.berkeley.edu *
|
||||
* http://www.cs.berkeley.edu/~mirtich *
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "momentOfInertia.H"
|
||||
//#include "pyramidPointFaceRef.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
//Foam::tensor Foam::momentOfInertia
|
||||
//(
|
||||
// const pointField& points,
|
||||
// const faceList& faces,
|
||||
// const cell& cFaces,
|
||||
// const point& cc
|
||||
//)
|
||||
//{
|
||||
// tensor t(tensor::zero);
|
||||
//
|
||||
// forAll(cFaces, i)
|
||||
// {
|
||||
// const face& f = faces[cFaces[i]];
|
||||
//
|
||||
// scalar pyrVol = pyramidPointFaceRef(f, cc).mag(points);
|
||||
//
|
||||
// vector pyrCentre = pyramidPointFaceRef(f, cc).centre(points);
|
||||
//
|
||||
// vector d = pyrCentre - cc;
|
||||
//
|
||||
// t.xx() += pyrVol*(sqr(d.y()) + sqr(d.z()));
|
||||
// t.yy() += pyrVol*(sqr(d.x()) + sqr(d.z()));
|
||||
// t.zz() += pyrVol*(sqr(d.x()) + sqr(d.y()));
|
||||
//
|
||||
// t.xy() -= pyrVol*d.x()*d.y();
|
||||
// t.xz() -= pyrVol*d.x()*d.z();
|
||||
// t.yz() -= pyrVol*d.y()*d.z();
|
||||
// }
|
||||
//
|
||||
// // Symmetric
|
||||
// t.yx() = t.xy();
|
||||
// t.zx() = t.xz();
|
||||
// t.zy() = t.yz();
|
||||
//
|
||||
// return t;
|
||||
//}
|
||||
|
||||
|
||||
#define sqr(x) ((x)*(x))
|
||||
#define pow3(x) ((x)*(x)*(x))
|
||||
|
||||
// compute various integrations over projection of face
|
||||
void Foam::compProjectionIntegrals
|
||||
(
|
||||
const pointField& points,
|
||||
const face& f,
|
||||
const direction A,
|
||||
const direction B,
|
||||
|
||||
scalar& P1,
|
||||
scalar& Pa,
|
||||
scalar& Pb,
|
||||
scalar& Paa,
|
||||
scalar& Pab,
|
||||
scalar& Pbb,
|
||||
scalar& Paaa,
|
||||
scalar& Paab,
|
||||
scalar& Pabb,
|
||||
scalar& Pbbb
|
||||
)
|
||||
{
|
||||
P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0;
|
||||
|
||||
forAll(f, i)
|
||||
{
|
||||
scalar a0 = points[f[i]][A];
|
||||
scalar b0 = points[f[i]][B];
|
||||
scalar a1 = points[f[(i+1) % f.size()]][A];
|
||||
scalar b1 = points[f[(i+1) % f.size()]][B];
|
||||
scalar da = a1 - a0;
|
||||
scalar db = b1 - b0;
|
||||
|
||||
scalar a0_2 = a0 * a0;
|
||||
scalar a0_3 = a0_2 * a0;
|
||||
scalar a0_4 = a0_3 * a0;
|
||||
|
||||
scalar b0_2 = b0 * b0;
|
||||
scalar b0_3 = b0_2 * b0;
|
||||
scalar b0_4 = b0_3 * b0;
|
||||
|
||||
scalar a1_2 = a1 * a1;
|
||||
scalar a1_3 = a1_2 * a1;
|
||||
|
||||
scalar b1_2 = b1 * b1;
|
||||
scalar b1_3 = b1_2 * b1;
|
||||
|
||||
scalar C1 = a1 + a0;
|
||||
|
||||
scalar Ca = a1*C1 + a0_2;
|
||||
scalar Caa = a1*Ca + a0_3;
|
||||
scalar Caaa = a1*Caa + a0_4;
|
||||
|
||||
scalar Cb = b1*(b1 + b0) + b0_2;
|
||||
scalar Cbb = b1*Cb + b0_3;
|
||||
scalar Cbbb = b1*Cbb + b0_4;
|
||||
|
||||
scalar Cab = 3*a1_2 + 2*a1*a0 + a0_2;
|
||||
scalar Kab = a1_2 + 2*a1*a0 + 3*a0_2;
|
||||
|
||||
scalar Caab = a0*Cab + 4*a1_3;
|
||||
scalar Kaab = a1*Kab + 4*a0_3;
|
||||
|
||||
scalar Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3;
|
||||
scalar Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3;
|
||||
|
||||
P1 += db*C1;
|
||||
Pa += db*Ca;
|
||||
Paa += db*Caa;
|
||||
Paaa += db*Caaa;
|
||||
Pb += da*Cb;
|
||||
Pbb += da*Cbb;
|
||||
Pbbb += da*Cbbb;
|
||||
Pab += db*(b1*Cab + b0*Kab);
|
||||
Paab += db*(b1*Caab + b0*Kaab);
|
||||
Pabb += da*(a1*Cabb + a0*Kabb);
|
||||
}
|
||||
|
||||
P1 /= 2.0;
|
||||
Pa /= 6.0;
|
||||
Paa /= 12.0;
|
||||
Paaa /= 20.0;
|
||||
Pb /= -6.0;
|
||||
Pbb /= -12.0;
|
||||
Pbbb /= -20.0;
|
||||
Pab /= 24.0;
|
||||
Paab /= 60.0;
|
||||
Pabb /= -60.0;
|
||||
}
|
||||
|
||||
|
||||
void Foam::compFaceIntegrals
|
||||
(
|
||||
const pointField& points,
|
||||
const face& f,
|
||||
const vector& n,
|
||||
const scalar w,
|
||||
const direction A,
|
||||
const direction B,
|
||||
const direction C,
|
||||
|
||||
scalar& Fa,
|
||||
scalar& Fb,
|
||||
scalar& Fc,
|
||||
scalar& Faa,
|
||||
scalar& Fbb,
|
||||
scalar& Fcc,
|
||||
scalar& Faaa,
|
||||
scalar& Fbbb,
|
||||
scalar& Fccc,
|
||||
scalar& Faab,
|
||||
scalar& Fbbc,
|
||||
scalar& Fcca
|
||||
)
|
||||
{
|
||||
scalar P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;
|
||||
|
||||
compProjectionIntegrals
|
||||
(
|
||||
points,
|
||||
f,
|
||||
A,
|
||||
B,
|
||||
|
||||
P1,
|
||||
Pa,
|
||||
Pb,
|
||||
Paa,
|
||||
Pab,
|
||||
Pbb,
|
||||
Paaa,
|
||||
Paab,
|
||||
Pabb,
|
||||
Pbbb
|
||||
);
|
||||
|
||||
scalar k1 = 1 / n[C];
|
||||
scalar k2 = k1 * k1;
|
||||
scalar k3 = k2 * k1;
|
||||
scalar k4 = k3 * k1;
|
||||
|
||||
Fa = k1 * Pa;
|
||||
Fb = k1 * Pb;
|
||||
Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1);
|
||||
|
||||
Faa = k1 * Paa;
|
||||
Fbb = k1 * Pbb;
|
||||
Fcc = k3 * (sqr(n[A])*Paa + 2*n[A]*n[B]*Pab + sqr(n[B])*Pbb
|
||||
+ w*(2*(n[A]*Pa + n[B]*Pb) + w*P1));
|
||||
|
||||
Faaa = k1 * Paaa;
|
||||
Fbbb = k1 * Pbbb;
|
||||
Fccc = -k4 * (pow3(n[A])*Paaa + 3*sqr(n[A])*n[B]*Paab
|
||||
+ 3*n[A]*sqr(n[B])*Pabb + pow3(n[B])*Pbbb
|
||||
+ 3*w*(sqr(n[A])*Paa + 2*n[A]*n[B]*Pab + sqr(n[B])*Pbb)
|
||||
+ w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1));
|
||||
|
||||
Faab = k1 * Paab;
|
||||
Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb);
|
||||
Fcca = k3 * (sqr(n[A])*Paaa + 2*n[A]*n[B]*Paab + sqr(n[B])*Pabb
|
||||
+ w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa));
|
||||
}
|
||||
|
||||
|
||||
void Foam::compVolumeIntegrals
|
||||
(
|
||||
const pointField& points,
|
||||
const faceList& faces,
|
||||
const cell& cFaces,
|
||||
const vectorField& fNorm,
|
||||
const scalarField& fW,
|
||||
|
||||
scalar& T0,
|
||||
vector& T1,
|
||||
vector& T2,
|
||||
vector& TP
|
||||
)
|
||||
{
|
||||
T0 = 0;
|
||||
T1 = vector::zero;
|
||||
T2 = vector::zero;
|
||||
TP = vector::zero;
|
||||
|
||||
forAll(cFaces, i)
|
||||
{
|
||||
const vector& n = fNorm[i];
|
||||
|
||||
scalar nx = mag(n[0]);
|
||||
scalar ny = mag(n[1]);
|
||||
scalar nz = mag(n[2]);
|
||||
|
||||
direction A, B, C;
|
||||
|
||||
if (nx > ny && nx > nz)
|
||||
{
|
||||
C = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
C = (ny > nz) ? 1 : 2;
|
||||
}
|
||||
|
||||
A = (C + 1) % 3;
|
||||
B = (A + 1) % 3;
|
||||
|
||||
scalar Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
|
||||
compFaceIntegrals
|
||||
(
|
||||
points,
|
||||
faces[cFaces[i]],
|
||||
n,
|
||||
fW[i],
|
||||
A,
|
||||
B,
|
||||
C,
|
||||
|
||||
Fa,
|
||||
Fb,
|
||||
Fc,
|
||||
Faa,
|
||||
Fbb,
|
||||
Fcc,
|
||||
Faaa,
|
||||
Fbbb,
|
||||
Fccc,
|
||||
Faab,
|
||||
Fbbc,
|
||||
Fcca
|
||||
);
|
||||
|
||||
T0 += n[0] * ((A == 0) ? Fa : ((B == 0) ? Fb : Fc));
|
||||
|
||||
T1[A] += n[A] * Faa;
|
||||
T1[B] += n[B] * Fbb;
|
||||
T1[C] += n[C] * Fcc;
|
||||
|
||||
T2[A] += n[A] * Faaa;
|
||||
T2[B] += n[B] * Fbbb;
|
||||
T2[C] += n[C] * Fccc;
|
||||
|
||||
TP[A] += n[A] * Faab;
|
||||
TP[B] += n[B] * Fbbc;
|
||||
TP[C] += n[C] * Fcca;
|
||||
}
|
||||
|
||||
T1 /= 2;
|
||||
T2 /= 3;
|
||||
TP /= 2;
|
||||
}
|
||||
|
||||
|
||||
// Calculate
|
||||
// - r: centre of mass
|
||||
// - J: inertia around origin (point 0,0,0)
|
||||
void Foam::momentOfIntertia
|
||||
(
|
||||
const pointField& points,
|
||||
const faceList& faces,
|
||||
const cell& cFaces,
|
||||
point& r,
|
||||
tensor& J
|
||||
)
|
||||
{
|
||||
// Face normals
|
||||
vectorField fNorm(cFaces.size());
|
||||
scalarField fW(cFaces.size());
|
||||
|
||||
forAll(cFaces, i)
|
||||
{
|
||||
label faceI = cFaces[i];
|
||||
|
||||
const face& f = faces[faceI];
|
||||
|
||||
fNorm[i] = f.normal(points);
|
||||
fNorm[i] /= mag(fNorm[i]) + VSMALL;
|
||||
|
||||
fW[i] = - (fNorm[i] & points[f[0]]);
|
||||
}
|
||||
|
||||
|
||||
scalar T0;
|
||||
vector T1, T2, TP;
|
||||
|
||||
compVolumeIntegrals
|
||||
(
|
||||
points,
|
||||
faces,
|
||||
cFaces,
|
||||
fNorm,
|
||||
fW,
|
||||
|
||||
T0,
|
||||
T1,
|
||||
T2,
|
||||
TP
|
||||
);
|
||||
|
||||
const scalar density = 1.0; /* assume unit density */
|
||||
|
||||
scalar mass = density * T0;
|
||||
|
||||
/* compute center of mass */
|
||||
r = T1 / T0;
|
||||
|
||||
/* compute inertia tensor */
|
||||
J.xx() = density * (T2[1] + T2[2]);
|
||||
J.yy() = density * (T2[2] + T2[0]);
|
||||
J.zz() = density * (T2[0] + T2[1]);
|
||||
J.xy() = J.yx() = - density * TP[0];
|
||||
J.yz() = J.zy() = - density * TP[1];
|
||||
J.zx() = J.xz() = - density * TP[2];
|
||||
|
||||
///* translate inertia tensor to center of mass */
|
||||
//J[XX] -= mass * (r[1]*r[1] + r[2]*r[2]);
|
||||
//J[YY] -= mass * (r[2]*r[2] + r[0]*r[0]);
|
||||
//J[ZZ] -= mass * (r[0]*r[0] + r[1]*r[1]);
|
||||
//J[XY] = J[YX] += mass * r[0] * r[1];
|
||||
//J[YZ] = J[ZY] += mass * r[1] * r[2];
|
||||
//J[ZX] = J[XZ] += mass * r[2] * r[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
75
src/meshTools/momentOfInertia/momentOfInertia.H
Normal file
75
src/meshTools/momentOfInertia/momentOfInertia.H
Normal file
@ -0,0 +1,75 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | Copyright (C) 2007-2009 OpenCFD Ltd.
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM 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.
|
||||
|
||||
OpenFOAM 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 OpenFOAM; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
Class
|
||||
momentOfInertia
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
momentOfInertia.H
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef momentOfInertia_H
|
||||
#define momentOfInertia_H
|
||||
|
||||
#include "tensor.H"
|
||||
#include "primitiveMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
////- Moment of inertia around cell centre for single cell.
|
||||
//tensor momentOfInertia
|
||||
//(
|
||||
// const pointField&,
|
||||
// const faceList&,
|
||||
// const cell&,
|
||||
// const point& cc
|
||||
//);
|
||||
|
||||
// Calculate
|
||||
// - centre of mass
|
||||
// - inertia tensor around (0,0,0)
|
||||
void momentOfIntertia
|
||||
(
|
||||
const pointField&,
|
||||
const faceList&,
|
||||
const cell&,
|
||||
point& r,
|
||||
tensor& Jorigin
|
||||
);
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
BIN
src/meshTools/momentOfInertia/volInt.ps.gz
Normal file
BIN
src/meshTools/momentOfInertia/volInt.ps.gz
Normal file
Binary file not shown.
146
src/meshTools/momentOfInertia/volumeIntegration/README
Normal file
146
src/meshTools/momentOfInertia/volumeIntegration/README
Normal file
@ -0,0 +1,146 @@
|
||||
1. OVERVIEW
|
||||
|
||||
This code accompanies the paper:
|
||||
|
||||
Brian Mirtich, "Fast and Accurate Computation of
|
||||
Polyhedral Mass Properties," journal of graphics
|
||||
tools, volume 1, number 2, 1996.
|
||||
|
||||
It computes the ten volume integrals needed for
|
||||
determining the center of mass, moments of
|
||||
inertia, and products of inertia for a uniform
|
||||
density polyhedron. From this information, a
|
||||
body frame can be computed.
|
||||
|
||||
To compile the program, use an ANSI compiler, and
|
||||
type something like
|
||||
|
||||
% cc volInt.c -O2 -lm -o volInt
|
||||
|
||||
|
||||
Revision history
|
||||
|
||||
26 Jan 1996 Program creation.
|
||||
|
||||
3 Aug 1996 Corrected bug arising when polyhedron density
|
||||
is not 1.0. Changes confined to function main().
|
||||
Thanks to Zoran Popovic for catching this one.
|
||||
|
||||
|
||||
|
||||
2. POLYHEDRON GEOMETRY FILES
|
||||
|
||||
The program reads a data file specified on the
|
||||
command line. This data file describes the
|
||||
geometry of a polyhedron, and has the following
|
||||
format:
|
||||
|
||||
N
|
||||
|
||||
x_0 y_0 z_0
|
||||
x_1 y_1 z_1
|
||||
.
|
||||
.
|
||||
.
|
||||
x_{N-1} y_{N-1} z_{N-1}
|
||||
|
||||
M
|
||||
|
||||
k1 v_{1,1} v_{1,2} ... v_{1,k1}
|
||||
k2 v_{2,1} v_{2,2} ... v_{2,k2}
|
||||
.
|
||||
.
|
||||
.
|
||||
kM v_{M,1} v_{M,2} ... v_{M,kM}
|
||||
|
||||
|
||||
where:
|
||||
N number of vertices on polyhedron
|
||||
x_i y_i z_i x, y, and z coordinates of ith vertex
|
||||
M number of faces on polyhedron
|
||||
ki number of vertices on ith face
|
||||
v_{i,j} jth vertex on ith face
|
||||
|
||||
In English:
|
||||
|
||||
First the number of vertices are specified. Next
|
||||
the vertices are defined by listing the 3
|
||||
coordinates of each one. Next the number of faces
|
||||
are specified. Finally, the faces themselves are
|
||||
specified. A face is specified by first giving
|
||||
the number of vertices around the polygonal face,
|
||||
followed by the (integer) indices of these
|
||||
vertices. When specifying indices, note that
|
||||
they must be given in counter-clockwise order
|
||||
(when looking at the face from outside the
|
||||
polyhedron), and the vertices are indexed from 0
|
||||
to N-1 for a polyhedron with N faces.
|
||||
|
||||
White space can be inserted (or not) as desired.
|
||||
Three example polyhedron geometry files are included:
|
||||
|
||||
cube A cube, 20 units on a side, centered at
|
||||
the origin and aligned with the coordinate axes.
|
||||
|
||||
tetra A tetrahedron formed by taking the convex
|
||||
hull of the origin, and the points (5,0,0),
|
||||
(0,4,0), and (0,0,3).
|
||||
|
||||
icosa An icosahedron with vertices lying on the unit
|
||||
sphere, centered at the origin.
|
||||
|
||||
|
||||
|
||||
3. RUNNING THE PROGRAM
|
||||
|
||||
Simply type,
|
||||
|
||||
% volInt <polyhedron geometry filename>
|
||||
|
||||
The program will read in the geometry of the
|
||||
polyhedron, and the print out the ten volume
|
||||
integrals.
|
||||
|
||||
The program also computes some of the mass
|
||||
properties which may be inferred from the volume
|
||||
integrals. A density of 1.0 is assumed, although
|
||||
this may be changed in function main(). The
|
||||
center of mass is computed as well as the inertia
|
||||
tensor relative to a frame with origin at the
|
||||
center of mass. Note, however, that this matrix
|
||||
may not be diagonal. If not, a diagonalization
|
||||
routine must be performed, to determine the
|
||||
orientation of the true body frame relative to
|
||||
the original model frame. The Jacobi method
|
||||
works quite well (see Numerical Recipes in C by
|
||||
Press, et. al.).
|
||||
|
||||
|
||||
|
||||
4. DISCLAIMERS
|
||||
|
||||
1. The volume integration code has been written
|
||||
to match the development and algorithms presented
|
||||
in the paper, and not with maximum optimization
|
||||
in mind. While inherently very efficient, a few
|
||||
more cycles can be squeezed out of the algorithm.
|
||||
This is left as an exercise. :)
|
||||
|
||||
2. Don't like global variables? The three
|
||||
procedures which evaluate the volume integrals
|
||||
can be combined into a single procedure with two
|
||||
nested loops. In addition to providing some
|
||||
speedup, all of the global variables can then be
|
||||
made local.
|
||||
|
||||
3. The polyhedron data structure used by the
|
||||
program is admittedly lame; much better schemes
|
||||
are possible. The idea here is just to give the
|
||||
basic integral evaluation code, which will have
|
||||
to be adjusted for other polyhedron data
|
||||
structures.
|
||||
|
||||
4. There is no error checking for the input
|
||||
files. Be careful. Note the hard limits
|
||||
#defined for the number of vertices, number of
|
||||
faces, and number of vertices per faces.
|
||||
21
src/meshTools/momentOfInertia/volumeIntegration/cube
Normal file
21
src/meshTools/momentOfInertia/volumeIntegration/cube
Normal file
@ -0,0 +1,21 @@
|
||||
8
|
||||
|
||||
-10 -10 -10
|
||||
+10 -10 -10
|
||||
+10 +10 -10
|
||||
-10 +10 -10
|
||||
-10 -10 +10
|
||||
+10 -10 +10
|
||||
+10 +10 +10
|
||||
-10 +10 +10
|
||||
|
||||
6
|
||||
|
||||
4 0 3 2 1
|
||||
4 4 5 6 7
|
||||
4 0 1 5 4
|
||||
4 6 2 3 7
|
||||
4 1 2 6 5
|
||||
4 0 4 7 3
|
||||
|
||||
|
||||
38
src/meshTools/momentOfInertia/volumeIntegration/icosa
Normal file
38
src/meshTools/momentOfInertia/volumeIntegration/icosa
Normal file
@ -0,0 +1,38 @@
|
||||
12
|
||||
|
||||
+0.00000000 +0.00000000 +1.00000000
|
||||
+0.00000000 +0.00000000 -1.00000000
|
||||
+0.89442719 +0.00000000 +0.44721360
|
||||
+0.27639320 +0.85065081 +0.44721360
|
||||
-0.72360680 +0.52573111 +0.44721360
|
||||
-0.72360680 -0.52573111 +0.44721360
|
||||
+0.27639320 -0.85065081 +0.44721360
|
||||
+0.72360680 +0.52573111 -0.44721360
|
||||
-0.27639320 +0.85065081 -0.44721360
|
||||
-0.89442719 +0.00000000 -0.44721360
|
||||
-0.27639320 -0.85065081 -0.44721360
|
||||
+0.72360680 -0.52573111 -0.44721360
|
||||
|
||||
20
|
||||
|
||||
3 6 11 2
|
||||
3 3 2 7
|
||||
3 7 2 11
|
||||
3 0 2 3
|
||||
3 0 6 2
|
||||
3 10 1 11
|
||||
3 1 7 11
|
||||
3 10 11 6
|
||||
3 8 7 1
|
||||
3 8 3 7
|
||||
3 5 10 6
|
||||
3 5 6 0
|
||||
3 4 3 8
|
||||
3 4 0 3
|
||||
3 9 8 1
|
||||
3 9 1 10
|
||||
3 4 5 0
|
||||
3 9 10 5
|
||||
3 9 5 4
|
||||
3 9 4 8
|
||||
|
||||
16
src/meshTools/momentOfInertia/volumeIntegration/tetra
Normal file
16
src/meshTools/momentOfInertia/volumeIntegration/tetra
Normal file
@ -0,0 +1,16 @@
|
||||
4
|
||||
|
||||
0 0 0
|
||||
5 0 0
|
||||
0 4 0
|
||||
0 0 3
|
||||
|
||||
4
|
||||
|
||||
3 0 3 2
|
||||
3 3 0 1
|
||||
3 2 1 0
|
||||
3 1 2 3
|
||||
|
||||
|
||||
|
||||
380
src/meshTools/momentOfInertia/volumeIntegration/volInt.c
Normal file
380
src/meshTools/momentOfInertia/volumeIntegration/volInt.c
Normal file
@ -0,0 +1,380 @@
|
||||
|
||||
|
||||
/*******************************************************
|
||||
* *
|
||||
* volInt.c *
|
||||
* *
|
||||
* This code computes volume integrals needed for *
|
||||
* determining mass properties of polyhedral bodies. *
|
||||
* *
|
||||
* For more information, see the accompanying README *
|
||||
* file, and the paper *
|
||||
* *
|
||||
* Brian Mirtich, "Fast and Accurate Computation of *
|
||||
* Polyhedral Mass Properties," journal of graphics *
|
||||
* tools, volume 1, number 1, 1996. *
|
||||
* *
|
||||
* This source code is public domain, and may be used *
|
||||
* in any way, shape or form, free of charge. *
|
||||
* *
|
||||
* Copyright 1995 by Brian Mirtich *
|
||||
* *
|
||||
* mirtich@cs.berkeley.edu *
|
||||
* http://www.cs.berkeley.edu/~mirtich *
|
||||
* *
|
||||
*******************************************************/
|
||||
|
||||
/*
|
||||
Revision history
|
||||
|
||||
26 Jan 1996 Program creation.
|
||||
|
||||
3 Aug 1996 Corrected bug arising when polyhedron density
|
||||
is not 1.0. Changes confined to function main().
|
||||
Thanks to Zoran Popovic for catching this one.
|
||||
|
||||
27 May 1997 Corrected sign error in translation of inertia
|
||||
product terms to center of mass frame. Changes
|
||||
confined to function main(). Thanks to
|
||||
Chris Hecker.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
constants
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
#define MAX_VERTS 100 /* maximum number of polyhedral vertices */
|
||||
#define MAX_FACES 100 /* maximum number of polyhedral faces */
|
||||
#define MAX_POLYGON_SZ 10 /* maximum number of verts per polygonal face */
|
||||
|
||||
#define X 0
|
||||
#define Y 1
|
||||
#define Z 2
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
macros
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
#define SQR(x) ((x)*(x))
|
||||
#define CUBE(x) ((x)*(x)*(x))
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
data structures
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
int numVerts;
|
||||
double norm[3];
|
||||
double w;
|
||||
int verts[MAX_POLYGON_SZ];
|
||||
struct polyhedron *poly;
|
||||
} FACE;
|
||||
|
||||
typedef struct polyhedron {
|
||||
int numVerts, numFaces;
|
||||
double verts[MAX_VERTS][3];
|
||||
FACE faces[MAX_FACES];
|
||||
} POLYHEDRON;
|
||||
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
globals
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
static int A; /* alpha */
|
||||
static int B; /* beta */
|
||||
static int C; /* gamma */
|
||||
|
||||
/* projection integrals */
|
||||
static double P1, Pa, Pb, Paa, Pab, Pbb, Paaa, Paab, Pabb, Pbbb;
|
||||
|
||||
/* face integrals */
|
||||
static double Fa, Fb, Fc, Faa, Fbb, Fcc, Faaa, Fbbb, Fccc, Faab, Fbbc, Fcca;
|
||||
|
||||
/* volume integrals */
|
||||
static double T0, T1[3], T2[3], TP[3];
|
||||
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
read in a polyhedron
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
void readPolyhedron(char *name, POLYHEDRON *p)
|
||||
{
|
||||
FILE *fp;
|
||||
char line[200], *c;
|
||||
int i, j, n;
|
||||
double dx1, dy1, dz1, dx2, dy2, dz2, nx, ny, nz, len;
|
||||
FACE *f;
|
||||
|
||||
|
||||
if (!(fp = fopen(name, "r"))) {
|
||||
printf("i/o error\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fscanf(fp, "%d", &p->numVerts);
|
||||
printf("Reading in %d vertices\n", p->numVerts);
|
||||
for (i = 0; i < p->numVerts; i++)
|
||||
fscanf(fp, "%lf %lf %lf",
|
||||
&p->verts[i][X], &p->verts[i][Y], &p->verts[i][Z]);
|
||||
|
||||
fscanf(fp, "%d", &p->numFaces);
|
||||
printf("Reading in %d faces\n", p->numFaces);
|
||||
for (i = 0; i < p->numFaces; i++) {
|
||||
f = &p->faces[i];
|
||||
f->poly = p;
|
||||
fscanf(fp, "%d", &f->numVerts);
|
||||
for (j = 0; j < f->numVerts; j++) fscanf(fp, "%d", &f->verts[j]);
|
||||
|
||||
/* compute face normal and offset w from first 3 vertices */
|
||||
dx1 = p->verts[f->verts[1]][X] - p->verts[f->verts[0]][X];
|
||||
dy1 = p->verts[f->verts[1]][Y] - p->verts[f->verts[0]][Y];
|
||||
dz1 = p->verts[f->verts[1]][Z] - p->verts[f->verts[0]][Z];
|
||||
dx2 = p->verts[f->verts[2]][X] - p->verts[f->verts[1]][X];
|
||||
dy2 = p->verts[f->verts[2]][Y] - p->verts[f->verts[1]][Y];
|
||||
dz2 = p->verts[f->verts[2]][Z] - p->verts[f->verts[1]][Z];
|
||||
nx = dy1 * dz2 - dy2 * dz1;
|
||||
ny = dz1 * dx2 - dz2 * dx1;
|
||||
nz = dx1 * dy2 - dx2 * dy1;
|
||||
len = sqrt(nx * nx + ny * ny + nz * nz);
|
||||
f->norm[X] = nx / len;
|
||||
f->norm[Y] = ny / len;
|
||||
f->norm[Z] = nz / len;
|
||||
f->w = - f->norm[X] * p->verts[f->verts[0]][X]
|
||||
- f->norm[Y] * p->verts[f->verts[0]][Y]
|
||||
- f->norm[Z] * p->verts[f->verts[0]][Z];
|
||||
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
compute mass properties
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
|
||||
/* compute various integrations over projection of face */
|
||||
void compProjectionIntegrals(FACE *f)
|
||||
{
|
||||
double a0, a1, da;
|
||||
double b0, b1, db;
|
||||
double a0_2, a0_3, a0_4, b0_2, b0_3, b0_4;
|
||||
double a1_2, a1_3, b1_2, b1_3;
|
||||
double C1, Ca, Caa, Caaa, Cb, Cbb, Cbbb;
|
||||
double Cab, Kab, Caab, Kaab, Cabb, Kabb;
|
||||
int i;
|
||||
|
||||
P1 = Pa = Pb = Paa = Pab = Pbb = Paaa = Paab = Pabb = Pbbb = 0.0;
|
||||
|
||||
for (i = 0; i < f->numVerts; i++) {
|
||||
a0 = f->poly->verts[f->verts[i]][A];
|
||||
b0 = f->poly->verts[f->verts[i]][B];
|
||||
a1 = f->poly->verts[f->verts[(i+1) % f->numVerts]][A];
|
||||
b1 = f->poly->verts[f->verts[(i+1) % f->numVerts]][B];
|
||||
da = a1 - a0;
|
||||
db = b1 - b0;
|
||||
a0_2 = a0 * a0; a0_3 = a0_2 * a0; a0_4 = a0_3 * a0;
|
||||
b0_2 = b0 * b0; b0_3 = b0_2 * b0; b0_4 = b0_3 * b0;
|
||||
a1_2 = a1 * a1; a1_3 = a1_2 * a1;
|
||||
b1_2 = b1 * b1; b1_3 = b1_2 * b1;
|
||||
|
||||
C1 = a1 + a0;
|
||||
Ca = a1*C1 + a0_2; Caa = a1*Ca + a0_3; Caaa = a1*Caa + a0_4;
|
||||
Cb = b1*(b1 + b0) + b0_2; Cbb = b1*Cb + b0_3; Cbbb = b1*Cbb + b0_4;
|
||||
Cab = 3*a1_2 + 2*a1*a0 + a0_2; Kab = a1_2 + 2*a1*a0 + 3*a0_2;
|
||||
Caab = a0*Cab + 4*a1_3; Kaab = a1*Kab + 4*a0_3;
|
||||
Cabb = 4*b1_3 + 3*b1_2*b0 + 2*b1*b0_2 + b0_3;
|
||||
Kabb = b1_3 + 2*b1_2*b0 + 3*b1*b0_2 + 4*b0_3;
|
||||
|
||||
P1 += db*C1;
|
||||
Pa += db*Ca;
|
||||
Paa += db*Caa;
|
||||
Paaa += db*Caaa;
|
||||
Pb += da*Cb;
|
||||
Pbb += da*Cbb;
|
||||
Pbbb += da*Cbbb;
|
||||
Pab += db*(b1*Cab + b0*Kab);
|
||||
Paab += db*(b1*Caab + b0*Kaab);
|
||||
Pabb += da*(a1*Cabb + a0*Kabb);
|
||||
}
|
||||
|
||||
P1 /= 2.0;
|
||||
Pa /= 6.0;
|
||||
Paa /= 12.0;
|
||||
Paaa /= 20.0;
|
||||
Pb /= -6.0;
|
||||
Pbb /= -12.0;
|
||||
Pbbb /= -20.0;
|
||||
Pab /= 24.0;
|
||||
Paab /= 60.0;
|
||||
Pabb /= -60.0;
|
||||
}
|
||||
|
||||
compFaceIntegrals(FACE *f)
|
||||
{
|
||||
double *n, w;
|
||||
double k1, k2, k3, k4;
|
||||
|
||||
compProjectionIntegrals(f);
|
||||
|
||||
w = f->w;
|
||||
n = f->norm;
|
||||
k1 = 1 / n[C]; k2 = k1 * k1; k3 = k2 * k1; k4 = k3 * k1;
|
||||
|
||||
Fa = k1 * Pa;
|
||||
Fb = k1 * Pb;
|
||||
Fc = -k2 * (n[A]*Pa + n[B]*Pb + w*P1);
|
||||
|
||||
Faa = k1 * Paa;
|
||||
Fbb = k1 * Pbb;
|
||||
Fcc = k3 * (SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb
|
||||
+ w*(2*(n[A]*Pa + n[B]*Pb) + w*P1));
|
||||
|
||||
Faaa = k1 * Paaa;
|
||||
Fbbb = k1 * Pbbb;
|
||||
Fccc = -k4 * (CUBE(n[A])*Paaa + 3*SQR(n[A])*n[B]*Paab
|
||||
+ 3*n[A]*SQR(n[B])*Pabb + CUBE(n[B])*Pbbb
|
||||
+ 3*w*(SQR(n[A])*Paa + 2*n[A]*n[B]*Pab + SQR(n[B])*Pbb)
|
||||
+ w*w*(3*(n[A]*Pa + n[B]*Pb) + w*P1));
|
||||
|
||||
Faab = k1 * Paab;
|
||||
Fbbc = -k2 * (n[A]*Pabb + n[B]*Pbbb + w*Pbb);
|
||||
Fcca = k3 * (SQR(n[A])*Paaa + 2*n[A]*n[B]*Paab + SQR(n[B])*Pabb
|
||||
+ w*(2*(n[A]*Paa + n[B]*Pab) + w*Pa));
|
||||
}
|
||||
|
||||
void compVolumeIntegrals(POLYHEDRON *p)
|
||||
{
|
||||
FACE *f;
|
||||
double nx, ny, nz;
|
||||
int i;
|
||||
|
||||
T0 = T1[X] = T1[Y] = T1[Z]
|
||||
= T2[X] = T2[Y] = T2[Z]
|
||||
= TP[X] = TP[Y] = TP[Z] = 0;
|
||||
|
||||
for (i = 0; i < p->numFaces; i++) {
|
||||
|
||||
f = &p->faces[i];
|
||||
|
||||
nx = fabs(f->norm[X]);
|
||||
ny = fabs(f->norm[Y]);
|
||||
nz = fabs(f->norm[Z]);
|
||||
if (nx > ny && nx > nz) C = X;
|
||||
else C = (ny > nz) ? Y : Z;
|
||||
A = (C + 1) % 3;
|
||||
B = (A + 1) % 3;
|
||||
|
||||
compFaceIntegrals(f);
|
||||
|
||||
T0 += f->norm[X] * ((A == X) ? Fa : ((B == X) ? Fb : Fc));
|
||||
|
||||
T1[A] += f->norm[A] * Faa;
|
||||
T1[B] += f->norm[B] * Fbb;
|
||||
T1[C] += f->norm[C] * Fcc;
|
||||
T2[A] += f->norm[A] * Faaa;
|
||||
T2[B] += f->norm[B] * Fbbb;
|
||||
T2[C] += f->norm[C] * Fccc;
|
||||
TP[A] += f->norm[A] * Faab;
|
||||
TP[B] += f->norm[B] * Fbbc;
|
||||
TP[C] += f->norm[C] * Fcca;
|
||||
}
|
||||
|
||||
T1[X] /= 2; T1[Y] /= 2; T1[Z] /= 2;
|
||||
T2[X] /= 3; T2[Y] /= 3; T2[Z] /= 3;
|
||||
TP[X] /= 2; TP[Y] /= 2; TP[Z] /= 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
============================================================================
|
||||
main
|
||||
============================================================================
|
||||
*/
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
POLYHEDRON p;
|
||||
double density, mass;
|
||||
double r[3]; /* center of mass */
|
||||
double J[3][3]; /* inertia tensor */
|
||||
|
||||
if (argc != 2) {
|
||||
printf("usage: %s <polyhedron geometry filename>\n", argv[0]);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
readPolyhedron(argv[1], &p);
|
||||
|
||||
compVolumeIntegrals(&p);
|
||||
|
||||
|
||||
printf("\nT1 = %+20.6f\n\n", T0);
|
||||
|
||||
printf("Tx = %+20.6f\n", T1[X]);
|
||||
printf("Ty = %+20.6f\n", T1[Y]);
|
||||
printf("Tz = %+20.6f\n\n", T1[Z]);
|
||||
|
||||
printf("Txx = %+20.6f\n", T2[X]);
|
||||
printf("Tyy = %+20.6f\n", T2[Y]);
|
||||
printf("Tzz = %+20.6f\n\n", T2[Z]);
|
||||
|
||||
printf("Txy = %+20.6f\n", TP[X]);
|
||||
printf("Tyz = %+20.6f\n", TP[Y]);
|
||||
printf("Tzx = %+20.6f\n\n", TP[Z]);
|
||||
|
||||
density = 1.0; /* assume unit density */
|
||||
|
||||
mass = density * T0;
|
||||
|
||||
/* compute center of mass */
|
||||
r[X] = T1[X] / T0;
|
||||
r[Y] = T1[Y] / T0;
|
||||
r[Z] = T1[Z] / T0;
|
||||
|
||||
/* compute inertia tensor */
|
||||
J[X][X] = density * (T2[Y] + T2[Z]);
|
||||
J[Y][Y] = density * (T2[Z] + T2[X]);
|
||||
J[Z][Z] = density * (T2[X] + T2[Y]);
|
||||
J[X][Y] = J[Y][X] = - density * TP[X];
|
||||
J[Y][Z] = J[Z][Y] = - density * TP[Y];
|
||||
J[Z][X] = J[X][Z] = - density * TP[Z];
|
||||
|
||||
/* translate inertia tensor to center of mass */
|
||||
J[X][X] -= mass * (r[Y]*r[Y] + r[Z]*r[Z]);
|
||||
J[Y][Y] -= mass * (r[Z]*r[Z] + r[X]*r[X]);
|
||||
J[Z][Z] -= mass * (r[X]*r[X] + r[Y]*r[Y]);
|
||||
J[X][Y] = J[Y][X] += mass * r[X] * r[Y];
|
||||
J[Y][Z] = J[Z][Y] += mass * r[Y] * r[Z];
|
||||
J[Z][X] = J[X][Z] += mass * r[Z] * r[X];
|
||||
|
||||
printf("center of mass: (%+12.6f,%+12.6f,%+12.6f)\n\n", r[X], r[Y], r[Z]);
|
||||
|
||||
printf("inertia tensor with origin at c.o.m. :\n");
|
||||
printf("%+15.6f %+15.6f %+15.6f\n", J[X][X], J[X][Y], J[X][Z]);
|
||||
printf("%+15.6f %+15.6f %+15.6f\n", J[Y][X], J[Y][Y], J[Y][Z]);
|
||||
printf("%+15.6f %+15.6f %+15.6f\n\n", J[Z][X], J[Z][Y], J[Z][Z]);
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user