vcpkg和cgal安裝和使用
1. 下載並安裝visual studio 2019
windows下最方便的安裝方式就是用visual studio來安裝, 並勾選使用C++的桌面開發
和右側的MSVC v142...
和Windows 10 SDK
。注意vcpkg會使用到$vswhereExe = "$programFiles\Microsoft Visual Studio\Installer\vswhere.exe"
,因此需要visual studio 2015及其以上版本才行。否則執行bootstrap-vcpkg.bat
會報錯。
2. 安裝vcpkg
在github上下載vcpkg,然後執行如下命令
bootstrap-vcpkg.bat
將會生成vcpkg.exe
檔案,將此加入到環境變數。
##3. 利用vcpkg安裝和解除安裝包
vcpkg install pkg:x64-windows
vcpkg remove pkg:x64-windows
安裝的包會放在cvpkg/packages
下面。
##4. 使用cgal
下載cgal的官方demo,然後使用cmake開啟:
cd Triangulation_2
mkdir build
cd build
cmake-gui ..
然後利用cmake指定Boost_DIR, CGAL, GMP, MPFR
Boost_INCLUDE_DIR D:\boost_1_72_0 CGAL_DIR D:/vcpkg/packages/cgal_x64-windows/share/cgal GMP_INCLUDE_DIR D:/vcpkg/packages/mpir_x64-windows/include GMP_LIBRARIES D:/vcpkg/packages/mpir_x64-windows/lib/mpir.lib MPFR_INCLUDE_DIR D:/vcpkg/packages/mpfr_x64-windows/include MPFR_LIBRARIES D:/vcpkg/packages/mpfr_x64-windows/lib/mpfr.lib
注意安裝cgal
包時要使用vcpkg install cgal[qt]:x64-windows
而不是直接使用vcpkg install cgal:x64-windows
。安裝完成之後再安裝qt
相關的包vcpkg install qt5:x64-windows
。然後指定
Qt5_DIR D:/vcpkg/packages/qt5-base_x64-windows/share/cmake/Qt5
否則會報錯:
The example draw_triangulation_2 requires Qt and will not be compiled.
注意libraries
一定要指定到具體的lib
檔案,否則在generate專案時會報如下錯誤:
WARNING: Target requests linking to directory Targets may link only to libraries. CMake is dropping the item.
然後在專案link
時會提示找不到lib
,即:
unresolved external symbol .....
。然後生成vs專案。在vs專案中可能需要進行額外配置。右擊工程,選擇Properties
,然後在"C/C++\general\Additional Include Directories"下面新增cgal,gmp(mpir), mpfr的相關include目錄。在Linker\General\Additional Library Directories
下面新增相應的lib
目錄以消除link時unresolved external symbol
的錯誤。然後執行時在Build Events\Post-Build Event
中的Command Line
下新增如下命令以消除dll missing
的錯誤:
xcopy /y /d "D:\vcpkg\packages\mpir_x64-windows\bin\mpir.dll" "$(outdir)"
如果需要拷貝多個dll檔案,則新增如下命令:
xcopy /y /d "D:\vcpkg\packages\qt5-base_x64-windows\debug\bin\*d.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\zlib_x64-windows\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\zlib_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\harfbuzz_x64-windows\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\libpng_x64-windows\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\libpng_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\icu_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\pcre2_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\zstd_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\freetype_x64-windows\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\freetype_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\bzip2_x64-windows\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\bzip2_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\brotli_x64-windows\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\brotli_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\qt5-svg_x64-windows\debug\bin\Qt5svgd.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\qt5-base_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\qt5-base_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\qt5-base_x64-windows\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\qt5-base_x64-windows\plugins\platforms\*.dll" "$(outdir)"
如果利用到qt
,執行時可能還會遇到以下錯誤:
qt.qpa.plugin: Could not find the Qt platform plugin "windows" in ""
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
此時需要將qt5-base_x64-windows\debug\plugins
下面的platforms\qwindowsd.dll
目錄拷貝到與exe
同級目錄下。網上說是拷貝qwindows.dll
,但在我的情況下需要拷貝qwindowsd.dll
檔案。至於其他的設定環境變數等其他solution
均無效。
5. 畫一個3d的Triangulations
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h>
#include <CGAL/point_generators_3.h>
#include <CGAL/draw_triangulation_3.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Delaunay_triangulation_3<K> DT3;
typedef CGAL::Creator_uniform_3<double, K::Point_3> Creator;
int main()
{
std::vector<K::Point_3> points;
CGAL::Random_points_in_sphere_3<K::Point_3, Creator> g(1.0);
std::copy_n(g, 50, std::back_inserter(points));
DT3 dt3(points.begin(), points.end());
CGAL::draw(dt3);
return EXIT_SUCCESS;
}
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-jHHJe1OI-1608775634192)(pics/30.png)]
如果執行沒問題,則證明所有安裝都成功。
6. 常見問題
如果畫圖時出現:
Impossible to draw, CGAL_USE_BASIC_VIEWER is not defined.
則需要參考examples
裡面的Tranigulation_2
裡面的CMakeLists.txt檔案,加入如下幾行
find_package(CGAL COMPONENTS Qt5)
if(CGAL_Qt5_FOUND)
add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS)
endif()
if(CGAL_FOUND)
file(GLOB cppfiles RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp)
foreach(cppfile ${cppfiles})
create_single_source_cgal_program( "${cppfile}" )
endforeach()
if(CGAL_Qt5_FOUND)
message(STATUS "Qt5 found")
target_link_libraries(draw_triangulation_2 PUBLIC CGAL::CGAL_Qt5)
else()
message(STATUS "NOTICE: The example draw_triangulation_2 requires Qt and will not be compiled.")
endif()
endif()
然後在vs的post-build的command-line裡拷貝如下dll
檔案:
xcopy /y /d "D:\vcpkg\packages\qt5-base_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\qt5-svg_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\zlib_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\harfbuzz_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\libpng_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\icu_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\pcre2_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\zstd_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\freetype_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\bzip2_x64-windows\debug\bin\*.dll" "$(outdir)"
xcopy /y /d "D:\vcpkg\packages\brotli_x64-windows\debug\bin\*.dll" "$(outdir)"
然後將上面的platforms\qwindowsd.dll
拷貝到相關目錄下。注意\
方向不能錯。
注意相關的檔案一定要放到與.sln
檔案同級的build
目錄下,即debug
的上級目錄。如果檔案沒找到可能不會有提示,因此可以加入以下幾行:
inline bool exist(const std::string& name)
{
std::ifstream file(name);
if(!file) // If the file was not found, then file is 0, i.e. !file=1 or true.
return false; // The file was not found.
else // If the file was found, then file is non-0.
return true; // The file was found.
}
然後呼叫:
if (exist(filename))
std::cout << "Good" << std::endl;
else
std::cout << "Bad" << std::endl;
7. 畫一個mesh
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/draw_surface_mesh.h>
#include <fstream>
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_3 Point;
typedef CGAL::Surface_mesh<Point> Mesh;
inline bool exist(const std::string& name)
{
std::ifstream file(name);
if (!file) // If the file was not found, then file is 0, i.e. !file=1 or true.
return false; // The file was not found.
else // If the file was found, then file is non-0.
return true; // The file was found.
}
int main(int argc, char* argv[])
{
Mesh sm1;
if(exist("data/elephant.off") )
std::cout << "Good" << std::endl;
else
std::cout << "bad" << std::endl;
std::ifstream in1((argc>1)?argv[1]:"data/elephant.off");
in1 >> sm1;
CGAL::draw(sm1);
return EXIT_SUCCESS;
}
8. CGAL基礎
CGAL的標頭檔案都在子目錄include\CGAL
中。所有的CGAL
類都在名稱空間CGAL
中,類以大寫字母開頭,全域性函式以小寫字母開頭,變數全部大寫,object
的維度作為字尾出現。
幾何原語(如點的型別)被定義為kernel
。
判斷3點是否共線:
#include <iostream>
#include <CGAL\Simple_cartesian.h>
using namespace std;
typedef CGAL::Simple_cartesian<double> Kernel;
typedef Kernel::Point_2 Point_2;
typedef Kernel::Segment_2 Segment_2;
int main()
{
Point_2 p(1, 1), q(10, 10);
cout << "p = " << p << endl;
cout << "q = " << q.x() << " " << q.y() << endl;
cout << "sqdist(p, q) = " << CGAL::squared_distance(p, q) << endl;
Segment_2 s(p, q);
Point_2 m(5, 9);
cout << "p, q, and m ";
switch (CGAL::orientation(p, q, m))
{
case CGAL::COLLINEAR:
cout << "are collinear\n";
break;
case CGAL::LEFT_TURN:
cout << "make a left turn\n";
break;
case CGAL::RIGHT_TURN:
cout << "make a right turn\n";
break;
}
cout << " midpoint(p, q) = " << CGAL::midpoint(p, q) << endl;
return 0;
}
計算凸包:
#include <iostream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/convex_hull_2.h>
using namespace std;
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
int main()
{
Point_2 points[5] = { Point_2(0, 0), Point_2(10, 0), Point_2(10, 10), Point_2(6, 5), Point_2(4, 1) };
Point_2 result[5];
Point_2* ptr = CGAL::convex_hull_2(points, points + 5, result);
cout << ptr - result << " points on the convex hull:" << endl;
for (int i = 0; i < ptr - result; i++)
{
cout << result[i] << endl;
}
return 0;
}
凸包結合vector
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/convex_hull_2.h>
#include <vector>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 Point_2;
typedef std::vector<Point_2> Points;
int main()
{
Points points, result;
points.push_back(Point_2(0, 0));
points.push_back(Point_2(10, 0));
points.push_back(Point_2(10, 10));
points.push_back(Point_2(6, 5));
points.push_back(Point_2(4, 1));
CGAL::convex_hull_2(points.begin(), points.end(), std::back_inserter(result));
std::cout << result.size() << " Points on the convex hull" << std::endl;
return 0;
}
visual studio中新增命令列引數:
Properties->Configuration Properties->Debugging->Command Arguments
,然後新增:
"-hide_banner" "Z:/media/subtitle/internal/divx/496x496.divx"
則傳遞給main函式的argc為3,其中argv[0]為程式名,argv[1]為"-hide_banner",argv[2]為"Z:/media/subtitle/internal/divx/496x496.divx"。各引數不是必須用"“引用起來,但使用”"可以防止引數本身有空格被誤判。
9. PLY檔案格式
CGAL::Surface_mesh<Point_3> output_mesh;
CGAL::poisson_surface_reconstruction_delaunay(
points.begin(), points.end(),
points.point_map(), points.normal_map(),
output_mesh, spacing
);
ofstream f("out.ply", std::ios_base::binary);
CGAL::set_ascii_mode(f);
//CGAL::set_binary_mode(f);
CGAL::write_ply(f, output_mesh);
f.close();
每個PLY檔都包含檔頭(header),用以設定網格模型的“元素”與“屬性”,以及在檔頭下方接著一連串的元素“數值資料”。一般而言,網格模型的“元素”就是頂點(vertices)、面(faces),另外還可能包含有邊(edges)、深度圖樣本(samples of range maps)與三角帶(triangle strips)等元素。無論是純文字與二元碼的PLY檔,檔頭資訊都是以ASCII編碼編寫,接續其後的數值資料才有編碼之分。
PLY檔案以此行作為開頭,以識別PLY格式。接著第二行是版本資訊,目前有三種寫法:
PLY
format ascii 1.0
format binary_little_endian 1.0
format binary_big_endian 1.0
其中ascii, binary_little_endian, binary_big_endian是檔案儲存的編碼方式,而1.0是遵循的標準版本(現階段僅有PLY 1.0版)。在檔頭中可使用’comment’作為一行的開頭以編寫註解。
描述元素及屬性,必須使用’element’及’property’的關鍵字,一般的格式為element下方接著屬性列表,例如:
element <element name> <number in file>
property <data_type> <property name 1>
property <data_type> <property name 2>
property <data_type> <property name 3>
property’不僅定義了資料的型態,其出現順序亦定義了資料的順序。內定的資料形態有兩種寫法:一種是char uchar short ushort int uint float double,另外一種是具有位元長度的int8 uint8 int16 uint16 int32 uint32 float32 float64。 例如,描述一個包含12個頂點的物體,每個頂點使用3個單精度浮點數 (x,y,z)代表點的座標,使用3個unsigned char代表頂點顏色,顏色順序為 (B, G, R),則檔頭的寫法為:
element vertex 12
property float x
property float y
property float z
property uchar blue
property uchar green
property uchar red
其中vertex是內定的元素型別,接續的6行property描述構成vertex元素的數值欄位順序代表的意義,及其資料形態。另一個常使用的元素是面。由於一個面是由3個以上的頂點所組成,因此使用一個“頂點列表”即可描述一個面, PLY格式使用一個特殊關鍵字’property list’定義之。 例如,一個具有10個面的物體,其PLY檔頭可能包含:
element face 10
property list uchar int vertex_indices
‘property list’表示該元素face的特性是由一行的頂點列表來描述。列表開頭以uchar型態的數值表示列表的專案數,後面接著資料型態為int的頂點索引值(vertex_indices),頂點索引值從0開始。
最後,標頭必須以此行結尾:
end_header
檔頭後接著的是元素資料(端點座標、拓樸連結等)。在ASCII格式中各個端點與面的資訊都是以獨立的一行描述,而二元編碼格式則連續儲存這些資料,載入時須以’element’定義的元素數目以及’property’中設定的資料形態計算各筆欄位的長度。
一個典型的PLY檔案結構分成三部分:
檔案頭 (從ply開始到end_header)
頂點元素列表
面元素列表
其中的頂點元素列表一般以x y z方式排列,形態如檔案頭所定義;而面元素列表是以下列格式表示。
<組成面的端點數N> <端點#1的索引> <端點#2的索引> ... <端點#N的索引>
存為ply
檔案之後,檔案組成如下:
ply
format ascii 1.0
comment made by anonymous
comment this file is a cube
element vertex 8
property float32 x
property float32 y
property float32 z
element face 12
property list uint8 int32 vertex_index
end_header
0 0 0
0 25.8 0
18.9 0 0
18.9 25.8 0
0 0 7.5
0 25.8 7.5
18.9 0 7.5
18.9 25.8 7.5
3 5 1 0
3 5 4 0
3 4 0 2
3 4 6 2
3 7 5 4
3 7 6 4
3 3 2 1
3 1 2 0
3 5 7 1
3 7 1 3
3 7 6 3
3 6 3 2
10. 從點雲檔案(.xyz)構建3維Mesh
#include <CGAL\Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL\Point_set_3.h>
#include <CGAL\Point_set_3\IO.h>
#include <CGAL\remove_outliers.h>
#include <CGAL\grid_simplify_point_set.h>
#include <CGAL\jet_estimate_normals.h>
#include <CGAL\jet_smooth_point_set.h>
#include <CGAL\mst_orient_normals.h>
#include <CGAL\poisson_surface_reconstruction.h>
#include <CGAL\Advancing_front_surface_reconstruction.h>
#include <CGAL\Scale_space_surface_reconstruction_3.h>
#include <CGAL\Scale_space_reconstruction_3\Jet_smoother.h>
#include <CGAL\Scale_space_reconstruction_3\Advancing_front_mesher.h>
#include <CGAL\Surface_mesh.h>
#include <CGAL\Polygon_mesh_processing\polygon_soup_to_polygon_mesh.h>
#include <CGAL\draw_surface_mesh.h>
#include <cstdlib>
#include <vector>
#include <fstream>
#include <iostream>
using namespace std;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::FT FT;
typedef Kernel::Point_3 Point_3;
typedef Kernel::Vector_3 Vector_3;
typedef Kernel::Sphere_3 Sphere_3;
typedef CGAL::Point_set_3<Point_3, Vector_3> Point_set;
int main(int argc, char* argv[])
{
Point_set points;
if (argc < 2)
{
cerr << "Usage: " << argv[0] << " [input.xyz/off/ply/las]" << endl;
return EXIT_FAILURE;
}
const char* input_file = argv[1];
ifstream stream(input_file, ios_base::binary);
if (!stream)
{
std::cerr << "Error: cannot read file " << input_file << std::endl;
return EXIT_FAILURE;
}
stream >> points;
cout << "Read " << points.size() << " point(s)" << endl;
if (points.empty())
return EXIT_FAILURE;
CGAL::remove_outliers<CGAL::Sequential_tag>(
points,
24, // Number of neighbors considered for evaluation
points.parameters().threshold_percent(5.0) // Percentage of points to remove
);
cout << points.number_of_removed_points() << " point(s) are outliers." << std::endl;
// Applying point set processing algorithm to a CGAL::Point_set_3
// object does not erase the points from memory but place them in
// the garbage of the object: memory can be freeed by the user.
points.collect_garbage();
// Compute average spacing using neighborhood of 6 points
double spacing = CGAL::compute_average_spacing<CGAL::Sequential_tag>(points, 6);
// Simplify using a grid of size 2 * average spacing
CGAL::grid_simplify_point_set(points, 2. * spacing);
cout << points.number_of_removed_points() << " point(s) removed after simplification." << std::endl;
points.collect_garbage();
CGAL::jet_smooth_point_set<CGAL::Sequential_tag>(points, 24);
unsigned int reconstruction_choice = (argc < 3 ? 0 : atoi(argv[2]));
if (reconstruction_choice == 0)//Poisson
{
CGAL::jet_estimate_normals<CGAL::Sequential_tag>(points, 24); // Use 24 neighbors
typename Point_set::iterator unoriented_points_begin = CGAL::mst_orient_normals(points, 24); // Use 24 neighbors
points.remove(unoriented_points_begin, points.end());
CGAL::Surface_mesh<Point_3> output_mesh;
CGAL::poisson_surface_reconstruction_delaunay(
points.begin(), points.end(),
points.point_map(), points.normal_map(),
output_mesh, spacing
);
CGAL::draw(output_mesh);
ofstream f("out.ply", std::ios_base::binary);
CGAL::set_ascii_mode(f);
//CGAL::set_binary_mode(f);
CGAL::write_ply(f, output_mesh);
f.close();
}
else if (reconstruction_choice == 1) //Advancing frong
{
typedef array<size_t, 3> Facet; // triple of indices
vector<Facet> facets;
// The function is called using directly the points raw iterators
CGAL::advancing_front_surface_reconstruction(
points.points().begin(),
points.points().end(),
back_inserter(facets)
);
cout << facets.size() << " facet(s) generated by reconstruction." << std::endl;
// copy points for random access
vector<Point_3> vertices;
vertices.reserve(points.size());
copy(points.points().begin(), points.points().end(), back_inserter(vertices));
CGAL::Surface_mesh<Point_3> output_mesh;
CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(vertices, facets, output_mesh);
ofstream f("out.off");
f << output_mesh;
f.close();
}
else if (reconstruction_choice == 2) // Scale space
{
CGAL::Scale_space_surface_reconstruction_3<Kernel> reconstruct
(points.points().begin(), points.points().end());
// Smooth using 4 iterations of Jet Smoothing
reconstruct.increase_scale(4, CGAL::Scale_space_reconstruction_3::Jet_smoother<Kernel>());
// Mesh with the Advancing Front mesher with a maximum facet length of 0.5
reconstruct.reconstruct_surface(CGAL::Scale_space_reconstruction_3::Advancing_front_mesher<Kernel>(0.5));
ofstream f("out.off");
f << "OFF" << endl << points.size() << " "
<< reconstruct.number_of_facets() << " 0" << endl;
for (Point_set::Index idx : points)
f << points.point(idx) << endl;
for (const auto& facet : CGAL::make_range(reconstruct.facets_begin(), reconstruct.facets_end()))
f << "3 " << facet << endl;
f.close();
}
else // Handle error
{
std::cerr << "Error: invalid reconstruction id: " << reconstruction_choice << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
資料檔案應該拷貝到build
目錄下,
11. kernel介紹
Exact_predicates_inexact_constructions_kernel
:A typedef to a kernel which has the following properties:
- It uses Cartesian representation.
- It supports constructions of points from double Cartesian coordinates.
- It provides exact geometric predicates, but inexact geometric constructions.
12 xyz檔案格式
xyz
為點雲檔案,格式如下:
-0.0721898 -0.159749 -0.108444 0.340472 0.937712 -0.0690972
0.145233 -0.163455 0.107108 0.821548 0.302589 0.483218
0.126784 -0.175123 -0.0474613 0.625688 0.275329 -0.729869
就是點座標的集合,前3個數帶標xyz,後面3個數代表法向量。
_predicates_inexact_constructions_kernel`:A typedef to a kernel which has the following properties:
- It uses Cartesian representation.
- It supports constructions of points from double Cartesian coordinates.
- It provides exact geometric predicates, but inexact geometric constructions.
12 xyz檔案格式
xyz
為點雲檔案,格式如下:
-0.0721898 -0.159749 -0.108444 0.340472 0.937712 -0.0690972
0.145233 -0.163455 0.107108 0.821548 0.302589 0.483218
0.126784 -0.175123 -0.0474613 0.625688 0.275329 -0.729869
就是點座標的集合,前3個數帶標xyz,後面3個數代表法向量。