Консультант
Регистрация: 28.06.2017
Сообщений: 555
Сказал(а) спасибо: 127
Поблагодарили 1,030 раз(а) в 366 сообщениях
Вес репутации: 344
|
Цитата:
Сообщение от Letos
Попытался сделать пример подсчёта площади поверхности для выделенного объекта, но сразу оговорюсь - кроме того, что считаются все треугольники (будут проблемы со стыками объектов, если считать суммарную площадь нескольких объектов), ещё, из-за операций с вещественными числами (в основном, деление и корень), будет возникать погрешность (скорее всего неприемлемая). Например: есть шар с радиусом 100. Его площадь поверхности: 4*Pi*R^2 = 125663.706. Скрипт же у меня выдаёт 110134.391.
Код для получения площади
PHP код:
// длина вектора
function VectorLength(v) {
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z)
}
/**
* Вычитание векторов
* @param {Vector} v1
* @param {Vector} v2
* @returns {Vector}
*/
function VectorSub(v1, v2) {
return {
x: v1.x - v2.x,
y: v1.y - v2.y,
z: v1.z - v2.z
}
}
/**
* Сложение векторов
* @param {Vector} v1
* @param {Vector} v2
* @returns {Vector}
*/
function VectorAdd(v1, v2) {
return {
x: v1.x + v2.x,
y: v1.y + v2.y,
z: v1.z + v2.z
}
}
// скалярное произведение векторов
function VectorDot(v1, v2) {
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z;
}
/**
* Проекция точки на линию
* @param {Vector} p Исходная точка
* @param {Vector} ls точка на линии
* @param {Vector} ld направление линии
* @returns {Vector}
*/
function PointLineProj(p, ls, ld) {
var v = VectorSub(p, ls)
var c1 = VectorDot(v, ld);
var c2 = VectorDot(ld, ld);
var c = c1 / c2;
return {
x: ls.x + ld.x * c,
y: ls.y + ld.y * c,
z: ls.z + ld.z * c
}
}
/**
* Расстояние от точки до линии
* @param {Vector} p Исходная точка
* @param {Vector} ls точка на линии
* @param {Vector} ld направление линии
*/
function PointLineDistance(p, ls, ld) {
var proj = PointLineProj(p, ls, ld);
var dv = VectorSub(proj, p);
return VectorLength(dv)
}
// Площадь треугольника - Основание * Высота / 2 (a*h/2)
// Точки p1, p2, p3 - вершины треугольника
// Если p1p2 - основание, тогда высота - расстояние от точки p3 до линии, на
// которой лежит основание.
//
// p3
// /|\
// / | \
// / | \
// / |h \
// /____|____\
// p1 a p2
//
function Square(tri) {
var p1 = tri.Vertex1, p2 = tri.Vertex2, p3 = tri.Vertex3;
var ld = VectorSub(p1, p2)
var a = VectorLength(ld);
var h = PointLineDistance(p3, p1, ld);
return a * h / 2;
}
var obj = Model.Selected;
var s = 0;
if (obj.TriListsCount > 0) {
for (var t = 0; t < obj.TriListsCount; t++) {
var list = obj.TriLists[t];
for (var i = 0; i < list.Count; i++) {
var tri = list[i];
if (tri) {
s += Square(tri);
}
}
}
}
alert('s = ' + s + 'mm');
[свернуть]
|
Некоторое время гуглил, как получше искать площадь поверхности и набрёл на англоязычную фразу "Surface Area". Оказалось, что у списка треугольников есть такой метод, поэтому скрипт может выглядеть гораздо короче:
PHP код:
var area = 0;
// Получение площади поверхности объекта
function GetSurfaceArea(obj){
var result = 0;
if (obj.TriListsCount > 0) {
for (var t = 0; t < obj.TriListsCount; t++) {
var list = obj.TriLists[t];
result += list.SurfaceArea();
}
}
return result;
}
//Обработка объекта и вложенных объектов.
function ProcessObject(obj){
if (obj.List){
for (var i = 0; i < obj.AsList().Count; i++){
ProcessObject(obj[i]);
}
}
else
area += GetSurfaceArea(obj);
}
for (var i = 0; i < Model.SelectionCount; i++){
var obj = Model.Selections[i];
ProcessObject(obj);
}
alert('Площадь поверхности выделенных объектов = ' + area + 'mm\u00b2');
P.S. Также я заметил, что погрешность вычислений зависит от параметров "Гладкость дуг" (меньше - хуже) и "ядро C3D" (выкл. - хуже).
Последний раз редактировалось Letos; 23.05.2019 в 17:15.
Причина: Удалил лишнюю цитату
|