| Правила | Регистрация | Пользователи | Сообщения за день |  Справка по форуму | Файлообменник |

Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Готовые программы > JavaScript. nanoCAD 5. Экспорт в файл геометрии Gmsh

JavaScript. nanoCAD 5. Экспорт в файл геометрии Gmsh

Ответ
Поиск в этой теме
Непрочитано 13.07.2021, 11:12 #1
JavaScript. nanoCAD 5. Экспорт в файл геометрии Gmsh
Нубий-IV
 
Инженер-философ
 
Хабаровск
Регистрация: 24.04.2019
Сообщений: 1,876

Самое сложное при создании геометрии в Gmsh - ввести координаты точек. Намного удобнее экспортировать геометрию из када. В автокаде есть экспорт *.iges, а нанокадчикам халявной версии поможет этот скрипт.
Код:
[Выделить все]
/*
 * Экспорт из nanoCAD в файл геометрии GMSH
 * 	Точки экспортируются в узлы
 * 	Отрезки - в линии
 * 	Круги - в четыре дуговых сегмента
 * 	Дуги - в дуговые сегменты не более 90° каждый
 *	Незамкнутые полилинии - в линии и дуги
 * 	Замкнутые полилинии - в плоские поверхности
 */


// Счетчики для нумерации объектов в файле
var nPoint = 0     // Номер следующей точки
var nCurve = 0     // Номер следующей кривой
var nCurveLoop = 0 // Номер следующего контура
var nSurface = 0   // Номер следующей поверхности


/**
 * Переводит точку из объектной системы координат в мировую.
 * @param {number[2]} point Точка в объектной системе координат
 * @param {number} elevation Возвышение объекта
 * @param {Object} normal Нормаль объекта
 * @returns {number[3]}
 */
function OCSarrayToWCSarray(point, elevation, normal) {
	var point3D = new Array(point[0], point[1], elevation)
	var pointOCS = Utility.CreateTypedArrayFromJSArray(5, point3D)
	var pointWCS = Utility.TranslateCoordinates(pointOCS, acOCS, acWorld, false, normal)
	return Utility.CreateSafeArrayFromVector(pointWCS).toArray()
}


/**
 * Возвращает скалярное произведение векторов
 * @param {number[3]} vector1 Первый вектор
 * @param {number[3]} vector2 Второй вектор
 * @returns {number}
 */
function DotProduct3D(vector1, vector2)
{
        return vector1[0] * vector2[0] + vector1[1] * vector2[1] + vector1[2] * vector2[2]
}


/**
 * Возвращает векторное произведение векторов
 * @param {number[3]} vector1 Первый вектор
 * @param {number[3]} vector2 Второй вектор
 * @returns {number[3]}
 */
function CrossProduct3D(vector1, vector2)
{
        return  [
                vector1[1] * vector2[2] - vector1[2] * vector2[1],
                vector1[2] * vector2[0] - vector1[0] * vector2[2],
                vector1[0] * vector2[1] - vector1[1] * vector2[0]
        ]
}


/**
 * Возвращает длину вектора
 * @param {number[2]} vector Вектор
 * @returns {number}
 */
function Length2D(vector)
{
        return Math.sqrt (
                Math.pow(vector[0], 2) +
                Math.pow(vector[1], 2))
}


/**
 * Возвращает длину вектора
 * @param {number[3]} vector Вектор
 * @returns {number}
 */
function Length3D(vector)
{
        return Math.sqrt (
                Math.pow(vector[0], 2) +
                Math.pow(vector[1], 2) +
                Math.pow(vector[2], 2))
}


/**
 * Возвращает нормализованный вектор
 * @param {number[3]} vector Вектор
 * @returns {number[3]}
 */
function Normalize3D(vector)
{
        Length = Length3D(vector)
        return [
                vector[0] / Length,
                vector[1] / Length,
                vector[2] / Length
        ]
}


/**
 * Возвращает разность векторов
 * @param {number[2]} vector1 Первый вектор
 * @param {number[2]} vector2 Второй вектор
 * @returns {number[2]}
 */
function Substract2D(vector1, vector2) {
	return [
		vector1[0] - vector2[0],
		vector1[1] - vector2[1]
	]
}


/**
 * Возвращает сумму векторов
 * @param {number[3]} vector1 Первый вектор
 * @param {number[3]} vector2 Второй вектор
 * @returns {number[3]}
 */
function Add3D(vector1, vector2) {
	return [
		vector1[0] + vector2[0],
		vector1[1] + vector2[1],
		vector1[2] + vector2[2],
	]
}


/**
 * Возвращает произведение вектора на множитель
 * @param {number} scalar Масштабный множитель
 * @param {number[3]} vector Вектор
 * @returns {number[3]}
 */
function Scale3D(scalar, vector)
{
	return [
		scalar * vector[0],
		scalar * vector[1],
		scalar * vector[2]
	]
}


/**
 * Возвращает произведение матрицы на вектор
 * @param {number[3][3]} matrix Матрица
 * @param {number[3]} vector Вектор
 * @returns {number[3]}
 */
function Multiply3D(matrix, vector)
{
	return [
		matrix[0][0] * vector[0] + matrix[0][1] * vector[1] + matrix[0][2] * vector[2],
		matrix[1][0] * vector[0] + matrix[1][1] * vector[1] + matrix[1][2] * vector[2],
		matrix[2][0] * vector[0] + matrix[2][1] * vector[1] + matrix[2][2] * vector[2]
	]
}


/**
 * Возвращает матрицу поворота вокруг заданной оси на заданный угол
 * @param {number[3]} axis Ось вращения
 * @param {number} angle Угол поворота
 * @returns {number[3][3]}
 */
function AxisRotationMatrix(axis, angle)
{
	var x = axis[0]
	var y = axis[1]
	var z = axis[2]

	var cos = Math.cos(angle)
	var sin = Math.sin(angle)

	return [
		[(1 - cos) * x * x + cos,       (1 - cos) * x * y - sin * z,   (1 - cos) * x * z + sin * y],
		[(1 - cos) * x * y + sin * z,   (1 - cos) * y * y + cos,       (1 - cos) * y * z - sin * x],
		[(1 - cos) * x * z - sin * y,   (1 - cos) * y * z + sin * x,   (1 - cos) * z * z + cos    ]
	]
}


/**
 * Возвращает результат поворота точки вокруг оси относительно центра
 * @param {number[3]} center Центр поворота
 * @param {number[3]} axis Ось поворота
 * @param {number[3]} point Точка
 * @param {number} angle Угол поворота
 * @returns {number[3]}
 */
function RotateCenterAxis3D(center, axis, point, angle)
{
	return Add3D(
		center, 
		Multiply3D(AxisRotationMatrix(axis, angle), point)
	)
}


/**
 * Возвращает начальную ось объекта
 * @param {number[3]} normal Нормаль объекта
 * @returns {number[3]}
 */
function ArbitraryAxisX(normal)
{
        if(Math.abs(normal[0]) < 1.0/64.0   &&   Math.abs(normal[1]) < 1.0/64.0) {
               var y = [0.0, 1.0, 0.0]
               return Normalize3D(CrossProduct3D(y, normal))
        } else {
                var z = [0.0, 0.0, 1.0]
                return Normalize3D(CrossProduct3D(z, normal))
        }
}


/**
 * Записывает точку в файл геометрии. Возвращает номер точи.
 * @param {number[3]} point Координаты точки
 * @returns {number}
 */
function WritePoint(point) {
	file.Write("Point(" + ++nPoint + ") = {" + point[0] + ", " + point[1] + ", " + point[2] + "};\n")
	return nPoint
}


/**
 * Записывает линию в файл геометрии. Возвращает номер линии.
 * @param {number} nStartPoint Номер начальной точки
 * @param {number} nEndPoint Номер конечной точки
 * @returns {number}
 */
function WriteLine(nStartPoint, nEndPoint) {
	file.Write("Line(" + ++nCurve + ") = {" + nStartPoint + ", " + nEndPoint + "};\n")
	return nCurve
}


/**
 * Записывает круговой сегмент в файл геометрии. Возвращает номер кругового сегмента.
 * @param {number} nStartPoint Номер начальной точки
 * @param {number} nCenterPoint Номер точки центра круга
 * @param {number} nEndPoint Номер конечной точки
 * @returns {number}
 */
function WriteCircle(nStartPoint, nCenterPoint, nEndPoint) {
	file.Write("Circle(" + ++nCurve + ") = {" + nStartPoint + ", " + nCenterPoint + ", " + nEndPoint + "};\n")
	return nCurve
}


/**
 * Записывает контур в файл геометрии. Возвращает номер контура.
 * @param {number[]} nCurves Массив номеров сегментов контура
 * @returns {number}
 */
function WriteCurveLoop(nCurves)
{
	file.Write("Curve Loop(" + ++nCurveLoop + ") = {" + nCurves + "};\n")
	return nCurveLoop
}


/**
 * Записывает плоскую поверхность в файл геометрии. Возвращает номер поверхности.
 * @param {number} nCurveLoop Номер контура поверхности
 * @returns {number}
 */
function WritePlaneSurface(nCurveLoop)
{
	file.Write("Plane Surface(" + ++nSurface + ") = {" + nCurveLoop + "};\n")
	return nSurface
}


/**
 * Экспортирует точку в файл геометрии
 * @param {AcDbPoint} point Точка
 */
function ExportPoint(point) {
	WritePoint(Utility.CreateSafeArrayFromVector(point.Coordinates).toArray())
}


/**
 * Экспортирует отрезок в файл геометрии
 * @param {AcDbLine} line Отрезок
 */
function ExportLine(line) {
	WriteLine(
		WritePoint(Utility.CreateSafeArrayFromVector(line.StartPoint).toArray()),
		WritePoint(Utility.CreateSafeArrayFromVector(line.EndPoint).toArray())
	)
}


/**
 * Возвращает направление из центра на первую точку круга
 * @param {number[3]} normal Нормаль круга
 * @returns {number[3]}
 */
function CircleDirection1(normal)
{
	if (normal[0] == 0) // Если нормаль в плоскости YOZ - направление вдоль Х
		return [1.0, 0.0, 0.0]
	
	if (normal[1] == 0) // Если нормаль в плоскости XOZ - направление вдоль Y
		return [0.0, 1.0, 0.0]
	
	// В остальных случаях - в плоскости XOY перпендикулярно нормали
	if (normal[0] / normal[1] <= 1) {
		var k = normal[0] / normal[1]
		var L = Math.sqrt(1 + k * k)
		return [1/L, -k/L, 0.0]
	} else {
		var k = normal[1] / normal[0]
		var L = Math.sqrt(1 + k * k)
		return [-k/L, 1/L, 0.0]
	}	
}


/**
 * Возвращает направление из центра на вторую точку круга
 * @param {number[3]} normal Нормаль круга
 * @param {number[3]} direction1 Направление на первую точку
 * @returns {number[3]}
 */
function CircleDirection2(normal, direction1)
{
	return CrossProduct3D(normal, direction1)
}


/**
 * Возвращает направление из центра на третью точку круга
 * @param {number[3]} direction1 Направление на первую точку
 * @returns {number[3]}
 */
function CircleDirection3(direction1)
{
	return Scale3D(-1, direction1)
}


/**
 * Возвращает направление из центра на четвертую точку круга
 * @param {number[3]} direction2 Направление на вторую точку
 * @returns {number[3]}
 */
function CircleDirection4(direction2)
{
	return Scale3D(-1, direction2)
}


/**
 * Экспортирует круг в файл геометрии
 * @param {AcDbCircle} circle Круг
 */
function ExportCircle(circle) {
	var center = Utility.CreateSafeArrayFromVector(circle.Center).toArray()
	var normal = Utility.CreateSafeArrayFromVector(circle.Normal).toArray()
	var R = circle.Radius

	// Запись в виде четырех дуговых сегментов
	var direction1 = CircleDirection1(normal)
	var direction2 = CircleDirection2(normal, direction1)
	var direction3 = CircleDirection3(direction1)
	var direction4 = CircleDirection4(direction2)

	var point1 = Add3D(center, Scale3D(R, direction1))
	var point2 = Add3D(center, Scale3D(R, direction2))
	var point3 = Add3D(center, Scale3D(R, direction3))
	var point4 = Add3D(center, Scale3D(R, direction4))

	var nPointCenter = WritePoint(center)

	var nPoint1 = WritePoint(point1)
	var nPoint2 = WritePoint(point2)
	var nPoint3 = WritePoint(point3)
	var nPoint4 = WritePoint(point4)

	WriteCircle(nPoint1, nPointCenter, nPoint2)
	WriteCircle(nPoint2, nPointCenter, nPoint3)
	WriteCircle(nPoint3, nPointCenter, nPoint4)
	WriteCircle(nPoint4, nPointCenter, nPoint1)
}


/**
 * Возвращает точку центра круга дугового сегмента полилинии в объектных координатах
 * @param {number[2]} vertex1 Первая вешшина сегмента
 * @param {number[2]} vertex2 Вторая вершина сегмента
 * @param {number} bulge Выпуклость сегмента
 * @returns {number[2]}
 */
function ArcSegmentCenterVertex(vertex1, vertex2, bulge)
{
	var L = Length2D(Substract2D(vertex2, vertex1))
	var H = L / 4 * (1 / bulge - bulge)
	return [
		(vertex1[0] + vertex2[0]) / 2 - (vertex2[1] - vertex1[1]) * H / L, 
		(vertex1[1] + vertex2[1]) / 2 + (vertex2[0] - vertex1[0]) * H / L
	]
}


/**
 * Возвращает среднюю точку дугового сегмента полилинии в объектных координатах
 * @param {number[2]} vertex1 Первая вешшина сегмента
 * @param {number[2]} vertex2 Вторая вершина сегмента
 * @param {number} bulge Выпуклость сегмента
 * @returns {number[2]}
 */
function ArcSegmentMiddleVertex(vertex1, vertex2, bulge)
{
	var L = Length2D(Substract2D(vertex2, vertex1))
	var S = L *  bulge / 2
	return [
		(vertex1[0] + vertex2[0]) / 2 + (vertex2[1] - vertex1[1]) * S / L, 
		(vertex1[1] + vertex2[1]) / 2 - (vertex2[0] - vertex1[0]) * S / L
	]
}



/**
 * Экспортирует полилинию в файл геометрии
 * @param {AcDbPolyline} polyline Полилиния
 */
function ExportPolyline(polyline) {
	var nv = (Utility.CreateSafeArrayFromVector(polyline.Coordinates).ubound() + 1) / 2

	var iFirst = 0
	var iLast = (polyline.Closed) ? nv - 1 : nv - 2

	var vertexFirst, vertex1, vertex2
	var nPointFirst, nPoint1, nPoint2

	var nCurves = [] // Список номеров сегментов для записи поверхности

	for (var iSegment = iFirst; iSegment <= iLast; iSegment++) {
		if (iSegment == iFirst) { // Для первого сегмента первая точка записываетя в файл
			vertex1 = vertexFirst = Utility.CreateSafeArrayFromVector(polyline.Coordinate(iSegment)).toArray()
			nPoint1 = nPointFirst = WritePoint(OCSarrayToWCSarray(vertex1, polyline.Elevation, polyline.Normal))
		} else { // Для следующих сегментов первая точка - это последняя точка предыдущего сегмента
			vertex1 = vertex2
			nPoint1 = nPoint2
		}

		if (iSegment == iLast && polyline.Closed) { // Для последнего сегмента замкнутой полилинии последняя точка - это первая точка полилинии
			vertex2 = vertexFirst
			nPoint2 = nPointFirst
		} else { // Для остальных сегментов последняя точка записывается в файл
			vertex2 = Utility.CreateSafeArrayFromVector(polyline.Coordinate(iSegment + 1)).toArray()
			nPoint2 = WritePoint(OCSarrayToWCSarray(vertex2, polyline.Elevation, polyline.Normal))
		}

		var bulge = polyline.GetBulge(iSegment)
		if (bulge == 0) { // Для прямолинейных сегментов записывается прямая
			nCurves.push(WriteLine(nPoint1, nPoint2))
		} else { // Для криволинейных сегментов записывается дуга
			var vertexCenter = ArcSegmentCenterVertex(vertex1, vertex2, bulge)
			var nPointCenter = WritePoint(OCSarrayToWCSarray(vertexCenter, polyline.Elevation, polyline.Normal))
			
			if(Math.abs(bulge) < 0.75) { // Для слабовыпуклых сегментов записывается одна дуга
				nCurves.push(WriteCircle(nPoint1, nPointCenter, nPoint2))
			} else { // Для сильновыпуклых сегментов записываеются две дуги через промежуточную точку
				var vertexMiddle = ArcSegmentMiddleVertex(vertex1, vertex2, bulge)
				var nPointMiddle = WritePoint(OCSarrayToWCSarray(vertexMiddle, polyline.Elevation, polyline.Normal))
				nCurves.push(WriteCircle(nPoint1, nPointCenter, nPointMiddle))
				nCurves.push(WriteCircle(nPointMiddle, nPointCenter, nPoint2))
			}
		}
	}
	if (polyline.Closed) // Для замкнутых полилиний записывается плоская поверхность
		WritePlaneSurface(WriteCurveLoop(nCurves))

}


/**
 * Возвращает точку дуги, заданную углом от начальной оси, в мировых координатах
 * @param {number[3]} center Центр дуги
 * @param {number[3]} normal Нормаль дуги
 * @param {number} radius Радиус дуги
 * @param {number} angle Угол точки
 * @returns {number[3]}
 */
function ArcPointAtAngle(center, normal, radius, angle)
{
	var axisX = ArbitraryAxisX(normal)
	var point = Scale3D(radius, axisX)
	return RotateCenterAxis3D(center, normal, point, angle)
}


/**
 * Экспортирует дугу в файл геометрии
 * @param {AcDbArc} arc Дуга
 */
function ExportArc(arc) {
	// Дуга делится на сегменты не более прямого угла
	var nSegments = Math.ceil(2 * arc.TotalAngle / Math.PI)

	// Дуга, у которой начальный угол больше конечного, строится с обратной стороны
	var startAngle = arc.StartAngle
	var endAngle = arc.EndAngle
	if(startAngle > endAngle) {
		startAngle -= 2 * Math.PI
	}

	var pStart = Utility.CreateSafeArrayFromVector(arc.StartPoint).toArray()
	var pCenter = Utility.CreateSafeArrayFromVector(arc.Center).toArray()
	var pEnd = Utility.CreateSafeArrayFromVector(arc.EndPoint).toArray()
	var normal = Utility.CreateSafeArrayFromVector(arc.Normal).toArray()

	var iFirstSegment = 0
	var iLastSegment = nSegments - 1

	var npStart, npEnd, npCenter

	for(var iSegment = 0; iSegment < nSegments; iSegment++) {
		if(iSegment == iFirstSegment) { // Для начального сегмента записывается центр и начальная точка дуги
			npCenter = WritePoint(pCenter)
			npStart = WritePoint(pStart)
		} else { // Для остальных сегментов первая точка - это последняя точна предыдущего сегмента
			npStart = npEnd
		}

		if(iSegment == iLastSegment) { // Для последнего сегмента последняя точка - это конечная точка дуги
			npEnd = WritePoint(pEnd)
		} else { // Для промежуточных сегментов последняя точка - это дополнительная промежуточная точка дуги
			var angle = startAngle * (nSegments - iSegment - 1) / nSegments + endAngle * (iSegment + 1) / nSegments
			npEnd = WritePoint(ArcPointAtAngle(pCenter, normal, arc.Radius, angle))
		}

		WriteCircle(npStart, npCenter, npEnd)
	}
}


/**
 * Экспортирует объект в файл геометрии
 * @param {AcDbEntity} entity Объект чертежа
 */
function ExportEntity(entity) {
	switch (entity.ObjectName) {
		case "AcDbPoint":
			ExportPoint(entity)
			break
		case "AcDbLine":
			ExportLine(entity)
			break
		case "AcDbCircle":
			ExportCircle(entity)
			break
		case "AcDbPolyline":
			ExportPolyline(entity)
			break
		case "AcDbArc":
			ExportArc(entity)
			break
	}
}


/**
* Возвращает имя файла, полученное от пользователя
* @param {Object} fso Объект FileSystemObject
* @param {String} defaultDirName Начальный путь для диалогового окна
*/
function GetFileName(fso, defaultDirName) {
	var chooseAllowNonexistent = 256
	var popupYesNoCancel = 3, popupExclamation = 48
	var popupCancel = 2, popupYes = 6, popupNo = 7

	var filename = ""
	var shell = new ActiveXObject("WScript.Shell")

	for (; ;) {
		filename = Utility.ChooseFile("file", "GMSH geometry |*.geo|Все файлы|*.*", chooseAllowNonexistent, defaultDirName)

		if (!filename)
			return ""

		if (fso.GetExtensionName(filename).toLowerCase() != "geo")
			filename += ".geo"

		if (fso.FileExists(filename)) {
			var userChoice = shell.Popup(filename + "\r\nФайл уже существует. Заменить?", 0, "Подтвердить сохранение", popupYesNoCancel + popupExclamation)
			switch (userChoice) {
				case popupYes:
					return filename
				case popupCancel:
					return ""
			}
		} else
			return filename

		defaultDirName = fso.GetParentFolderName(filename)
	}
}


// Объект доступа к файловой системе
var fso = new ActiveXObject("Scripting.FileSystemObject")

// Запрос имени файла
var defaultDirName = ""
var filename = GetFileName(fso, defaultDirName)

// Запись файла
if (filename) {
	// Файл геометрии GMSH
	var file = fso.OpenTextFile(filename, 2, true)

	// Фильтр выбора объектов
	var FilterType = [0]
	var FilterData = ["POINT,LINE,CIRCLE,LWPOLYLINE,ARC"]

	FilterType = Utility.CreateTypedArrayFromJSArray(2, FilterType)
	FilterData = Utility.CreateTypedArrayFromJSArray(8, FilterData)

	// Выбор объектов
	Utility.Prompt("Экспорт в файл геометрии GMSH")
	ActiveSelectionSet.SelectOnScreen(FilterType, FilterData)

	// Экспорт выбранных объектов
	for (var i = 0; i < ActiveSelectionSet.Count; i++)
		ExportEntity(ActiveSelectionSet.Item(i))

	// Сброс выделения
	ActiveSelectionSet.Clear()
}
  • Элементы без отверстий (полки, стенки, швы) заданы замкнутыми полилиниями.
  • Элементы с отверстиями (фланцы, дырявая стенка колонны) - незамкнутыми полилиниями и кругами отверстий. Не бывает полилиний с отверстиями, и такие части приходится доделывать в Gmsh, при готовых контурах это делается быстро.
  • В местах, где один элемент касается углом стороны другого элемента (то есть узел попадает на сторону линии), добавлены дополнительные узлы в полилиниях (см. полки колонны и фланец), иначе при создании сетки будут глюки с очень мелкими элементами возле такого висячего узла.
После импорта в Gmsh:
  • Выполнено слияние совпадающих элементов (Geometry / Elementary entities / Coherence)
  • Заданы поверхности с отверстиями - фланцы и стенка колонны (Geometry / Elementary entities / Add / Plane Surface)
  • Настроена генерация совместной сетки в местах, где одни элементы касаются поверхности других (Mesh / Define / Embedded / Curve)
  • Сгененрирована сетка (Алгоритм Frontal-Delaunay for Quads), и объединенина в четырехугольники (Алгоритм рекомбинации - Simple)

Миниатюры
Нажмите на изображение для увеличения
Название: ExportGEO.png
Просмотров: 164
Размер:	249.3 Кб
ID:	238832  

Вложения
Тип файла: zip Пример.zip (484.6 Кб, 18 просмотров)

Просмотров: 2077
Ответ
Вернуться   Форум DWG.RU > Программное обеспечение > Программирование > Готовые программы > JavaScript. nanoCAD 5. Экспорт в файл геометрии Gmsh

Размещение рекламы


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Различные продукты nanoCAD . Помогите в выборе. Alexandr_A Другие CAD системы 11 18.06.2015 12:42
Как преобразовать .dwg файл в .txt файл? BuTeR:D AutoCAD 30 16.10.2013 10:38
"Файл рисунка испорчен" - не та версия Акад или реально нерабочий файл? Ернат Разное 3 17.06.2009 09:56
Экспорт свойств группы объектов из AutoCAD в текстовый файл ASh666 AutoCAD 2 02.06.2009 11:15
как пребразовать файл картинку типа pdf в графическй файл dwg& stas50 AutoCAD 6 05.05.2009 13:53