I have this setup:
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Triangulation_vertex_base_with_info_2<FIntPoint, K> Vb;
typedef CGAL::Constrained_triangulation_face_base_2<K> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
typedef CGAL::Exact_predicates_tag Itag;
typedef CGAL::Constrained_Delaunay_triangulation_2<K, Tds, Itag> Delaunay;
typedef Delaunay::Point Point;
typedef Delaunay::Vertex_handle VertexHandle;
FIntPoint is a struct with 2 integers.
My vertices belong to border triangles of 2 separate terrain-like 3D meshes. I triangulate these vertices in 2D to connect these meshes. The info I need for each vertex is (1) which mesh it belongs to and (2) its vertex index within that mesh, so that I know where this vertex came from after triangulation, as more information is tied to these indices.
In this illustration, you can see the 2 meshes and their border triangles. I want to stitch these together:
This is basically how I insert points, simplified:
Delaunay Triangulation;
for (...)
{
// Insert a triangle from one of my meshes
VertexHandle vh1 = Triangulation.insert(Point(a.Y, a.Z));
vh1->info() = FIntPoint(iA, iM);
VertexHandle vh2 = Triangulation.insert(Point(b.Y, b.Z));
vh2->info() = FIntPoint(iB, iM);
VertexHandle vh3 = Triangulation.insert(Point(c.Y, c.Z));
vh3->info() = FIntPoint(iC, iM);
// Add constraints to keep this triangle exactly how it was in the origin mesh
Triangulation.insert_constraint(vh1, vh2);
Triangulation.insert_constraint(vh2, vh3);
Triangulation.insert_constraint(vh3, vh1);
}
My problem now is that when I try to retrieve the info, it is missing/incorrect. I get values outside of the range I'm inserting them.
This happens only with the constraints. When I comment out the lines with insert_constraint, it works as expected.
for (auto itFace = Triangulation.finite_faces_begin(); itFace != Triangulation.finite_faces_end(); itFace++)
{
// Retrieve vertex info
auto& a = itFace->vertex(0)->info();
auto& b = itFace->vertex(1)->info();
auto& c = itFace->vertex(2)->info();
// ...
}
What am I doing wrong with the constraints?
Additionally, I want to limit the length of edges. I haven't attempted so add this limitation in my code yet, because I wanted to fix the described problem first. If you could provide an answer that includes a maximum edge length, that would be very helpful too.
Any help is appreciated. I've been sitting on this problem for a long time.
Related
From the CGAL documentation, one can create an alpha_shape_2 from a Delaunay triangulation:
CGAL::Alpha_shape_2< Dt, ExactAlphaComparisonTag >::Alpha_shape_2(Dt& dt, FT alpha = 0, Mode m = GENERAL)
However the operation destroys the triangulation.
In my problem I have a bunch of points which are triangulated. I need to identify the "right" triangles using the alpha shape algorithm. I already computed that myself from the delaunay triangulation (computing the circumcircle radius myself and so on), since I did not find a way to extract the remaining triangles from alpha_shape_2 (I can extract the edges of the alpha shape but not the inner triangles). Is it only possible using CGAL ?
For example in matlab (ouch) one can do:
shp = alphaShape(points.x,points.y);
shp.Alpha = alpha;
tri = alphaTriangulation(shp);
bf = boundaryFacets(shp);
Side question: what is the definition of the alpha value of cgal ? Mine is : r_c/h>alpha, where r_c is the triangle circumcircle radius and h and size parameter?
For the side question see this section. About your initial question I'm not sure to understand precisely what you want to get but you can iterate all the triangles and get their classification using the following code:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Alpha_shape_2.h>
#include <CGAL/Alpha_shape_vertex_base_2.h>
#include <CGAL/Alpha_shape_face_base_2.h>
#include <CGAL/Delaunay_triangulation_2.h>
#include <vector>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::FT FT;
typedef K::Point_2 Point;
typedef CGAL::Alpha_shape_vertex_base_2<K> Vb;
typedef CGAL::Alpha_shape_face_base_2<K> Fb;
typedef CGAL::Triangulation_data_structure_2<Vb,Fb> Tds;
typedef CGAL::Delaunay_triangulation_2<K,Tds> Triangulation_2;
typedef CGAL::Alpha_shape_2<Triangulation_2> Alpha_shape_2;
int main()
{
std::vector<Point> points;
double alpha;
Alpha_shape_2 A(points.begin(), points.end(),
alpha,
Alpha_shape_2::GENERAL);
for (Alpha_shape_2::Finite_faces_iterator fit=A.finite_faces_begin();
fit!=A.finite_faces_end();++fit)
{
switch(A.classify(fit))
{
case Alpha_shape_2::REGULAR:
break;
case Alpha_shape_2::SINGULAR:
break;
case Alpha_shape_2::EXTERIOR:
break;
case Alpha_shape_2::INTERIOR:
break;
}
}
return 0;
}
Imagine this piece of code:
void Function(int16 *src, int *indices, float *dst, int cnt, float mul)
{
for (int i=0; i<cnt; i++) dst[i] = float(src[indices[i]]) * mul;
};
This really asks for gather intrinsics e.g. _mm_i32gather_epi32. I got great success with these when loading floats, but are there any for 16-bit ints? Another problem here is that I need to transition from 16-bits on the input to 32-bits (float) on the output.
There is indeed no instruction to gather 16bit integers, but (assuming there is no risk of memory-access violation) you can just load 32bit integers starting at the corresponding addresses, and mask out the upper halves of each value.
For uint16_t this would be a simple bit-and, for signed integers you can shift the values to the left in order to have the sign bit at the most-significant position. You can then (arithmetically) shift back the values before converting them to float, or, since you multiply them anyway, just scale the multiplication factor accordingly.
Alternatively, you could load from two bytes earlier and arithmetically shift to the right. Either way, your bottle-neck will likely be the load-ports (vpgatherdd requires 8 load-uops. Together with the load for the indices you have 9 loads distributed on two ports, which should result in 4.5 cycles for 8 elements).
Untested possible AVX2 implementation (does not handle the last elements, if cnt is not a multiple of 8 just execute your original loop at the end):
void Function(int16_t const *src, int const *indices, float *dst, size_t cnt, float mul_)
{
__m256 mul = _mm256_set1_ps(mul_*float(1.0f/0x10000));
for (size_t i=0; i+8<=cnt; i+=8){ // todo handle last elements
// load indicies:
__m256i idx = _mm256_loadu_si256(reinterpret_cast<__m256i const*>(indices + i));
// load 16bit integers in the lower halves + garbage in the upper halves:
__m256i values = _mm256_i32gather_epi32(reinterpret_cast<int const*>(src), idx, 2);
// shift each value to upper half (removes garbage, makes sure sign is at the right place)
// values are too large by a factor of 0x10000
values = _mm256_slli_epi32(values, 16);
// convert to float, scale and multiply:
__m256 fvalues = _mm256_mul_ps(_mm256_cvtepi32_ps(values), mul);
// store result
_mm256_storeu_ps(dst, fvalues);
}
}
Porting this to AVX-512 should be straight-forward.
I have a CGAL::Point_set_3 point set with point normal and color. I would like to save all properties to a PLY file, using write_ply_with_properties() function.
My goal is to make the full version work (see code below), but even the simple version doesn't compile, with the same error as the full version.
I work on Linux with CGAL release 4.14 and gcc 7.4.0.
Here is the code:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Point_set_3.h>
#include <CGAL/Point_set_3/IO.h>
#include <tuple> // for std::tie
#include <fstream>
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point;
typedef Kernel::Vector_3 Vector;
typedef CGAL::Point_set_3<Point> Point_set;
int main(int argc, char*argv[])
{
Point_set points;
points.insert(Point(1., 2., 3.));
points.insert(Point(4., 5., 6.));
// add normal map
points.add_normal_map();
auto normal_map = points.normal_map();
// add color map
typedef Point_set::Property_map< Vector > ColorMap;
bool success = false;
ColorMap color_map;
std::tie(color_map, success) =
points.add_property_map< Vector >("color");
assert(success);
// populate normal and color map
for(auto it = points.begin(); it != points.end(); ++it)
{
normal_map[*it] = Vector(10., 11., 12.);
color_map[*it] = Vector(20., 21., 22.);
}
std::ofstream out("out.ply");
#if 1
// simple version
if(!out || !CGAL::write_ply_points_with_properties(
out,
points.points(), // const PointRange
CGAL::make_ply_point_writer(points.point_map())))
#else
// full version
if(!out || !CGAL::write_ply_points_with_properties(
out,
points.points(), // const PointRange
CGAL::make_ply_point_writer(points.point_map()),
CGAL::make_ply_normal_writer(points.normal_map()),
std::make_tuple(color_map,
CGAL::PLY_property< double >("red"),
CGAL::PLY_property< double >("green"),
CGAL::PLY_property< double >("blue"))))
#endif
{
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
The compilation error is:
...
/usr/include/boost/property_map/property_map.hpp:303:54: error: no match for ‘operator[]’ (operand types are ‘const CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Property_map<CGAL::Point_3<CGAL::Epick> >’ and ‘const CGAL::Point_3<CGAL::Epick>’)
Reference v = static_cast<const PropertyMap&>(pa)[k];
CGAL-4.14/include/CGAL/Surface_mesh/Properties.h:567:15: note: candidate: CGAL::Properties::Property_map_base<I, T, CRTP_derived_class>::reference CGAL::Properties::Property_map_base<I, T, CRTP_derived_class>::operator[](const I&) [with I = CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Index; T = CGAL::Point_3<CGAL::Epick>; CRTP_derived_class = CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Property_map<CGAL::Point_3<CGAL::Epick> >; CGAL::Properties::Property_map_base<I, T, CRTP_derived_class>::reference = CGAL::Point_3<CGAL::Epick>&]
reference operator[](const I& i)
^~~~~~~~
CGAL-4.14/include/CGAL/Surface_mesh/Properties.h:567:15: note: no known conversion for argument 1 from ‘const CGAL::Point_3<CGAL::Epick>’ to ‘const CGAL::Point_set_3<CGAL::Point_3<CGAL::Epick> >::Index&’
How can I fix it?
The problem in your code is that you are using the method points() of CGAL::Point_set_3 which returns a range of points of type CGAL::Point_set_3::Point_range, whereas the property maps that you use (points.point_map(), etc.) are directly applied to a type CGAL::Point_set_3.
So you should simply call the write_ply_points_with_properties() on points, not on points.points().
Note also that if you store your colors on simple types (for example, using three Point_set_3 properties typed unsigned char), you can take advantage of the function CGAL::write_ply_point_set() that will automatically write all the simply-typed properties it finds, which makes it quite straightforward to use (just do CGAL::write_ply_point_set(out, points) and you're done).
One last thing that is really a detail not related to your problem, but you should avoid using the CGAL::Vector_3 for storing anything else than an actual geometric 3D vector (like colors in your case). That makes your code harder to read and is also quite an ineffective way to store colors if they are encoded as integer values between 0 and 255 (which is what unsigned char is for).
I want to access a StructuredBuffer<int>in a compute shader but I get the error:
Shader error in 'Particle.compute': array, matrix, vector, or indexable object type expected in index expression at Particle.compute(28) (on d3d11)
The code:
#pragma kernel CSMain
#include "Assets/Uplus/ZCommon/Resources/ImageProcessing/UplusDirectCompute.cginc"
struct Particle
{
float3 Position;
float Mass;
};
Texture2D<float2> _terTx;
ConsumeStructuredBuffer<Particle> currentBuffer;
AppendStructuredBuffer<Particle> nextBuffer;
StructuredBuffer<int> particleCount;
float3 _terPos;
float _terSize, _terPhysicalScale, _resolution;
SamplerState _LinearClamp;
SamplerState _LinearRepeat;
#define _gpSize 512
[numthreads(_gpSize, 1, 1)]
void CSMain(uint3 dispatchID : SV_DispatchThreadID)
{
int flatID = dispatchID.x;
int particleCount = particleCount[0];
if (flatID >= particleCount) return;
Particle particle = currentBuffer.Consume();
//Commented the rest of code
nextBuffer.Append(particle);
}
The error points the line int particleCount = particleCount[0];. Why is that?
The whole idea behind the shader is we have two buffers. We fill one with some data (we call each of them Particle) from CPU and then in the shader consume the data from the buffer, process it and then append to another buffer. then we swap buffers and do another iteration. The particleCount buffer holds the current count of Particles that the buffer holds and the if clause prevents from consuming more Particles than available.
This is an old question so I assume you solved it, but here is the answer anyway:
You are declaring particleCount as an int when it already is a buffer.
Either change the name to int currentParticleCount = particleCount[0]; or just don't use a temporary variable:
if (flatID >= particleCount[0]) return;
I'd like to do refinement of eg a simple cube (from a .off); there are a few ways but the ones suitable for what I want to do next end up with 'wrinkles', ie the object shape gets distorted.
This way below promises to allow the boundaries (shape?) of the object to be preserved, permitting what you'd expect of refinement, to just add more edges and vertices:
http://doc.cgal.org/latest/Polygon_mesh_processing/Polygon_mesh_processing_2isotropic_remeshing_example_8cpp-example.html
I want an edge constraint map (and if that isn't sufficient then I'll want a vertex constraint map as well) but can't figure out the template abstractions well enough. I tried an OpenMesh Constrained_edge_map from a different CGAL example, but that's too different and won't compile. What I'm asking for is an edge map and maybe a vertex map that I can feed to the call:
PMP::isotropic_remeshing(
faces(mesh),
target_edge_length,
mesh,
PMP::parameters::number_of_iterations(nb_iter)
.protect_constraints(true)//i.e. protect border, here
);
I'm using CGAL 4.8.1, the latest at time of writing. Thanks.
Here is a minimal example to remesh a triangulated cube:
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/boost/graph/graph_traits_Surface_mesh.h>
#include <CGAL/Polygon_mesh_processing/remesh.h>
#include <CGAL/Mesh_3/dihedral_angle_3.h>
#include <boost/foreach.hpp>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Surface_mesh<K::Point_3> Mesh;
typedef boost::graph_traits<Mesh>::halfedge_descriptor halfedge_descriptor;
typedef boost::graph_traits<Mesh>::edge_descriptor edge_descriptor;
namespace PMP=CGAL::Polygon_mesh_processing;
int main(int, char* argv[])
{
std::ifstream input(argv[1]);
Mesh tmesh;
input >> tmesh;
double target_edge_length = 0.20;
unsigned int nb_iter = 10;
// give each vertex a name, the default is empty
Mesh::Property_map<edge_descriptor,bool> is_constrained =
tmesh.add_property_map<edge_descriptor,bool>("e:is_constrained",false).first;
//detect sharp features
BOOST_FOREACH(edge_descriptor e, edges(tmesh))
{
halfedge_descriptor hd = halfedge(e,tmesh);
if ( !is_border(e,tmesh) ){
double angle = CGAL::Mesh_3::dihedral_angle(tmesh.point(source(hd,tmesh)),
tmesh.point(target(hd,tmesh)),
tmesh.point(target(next(hd,tmesh),tmesh)),
tmesh.point(target(next(opposite(hd,tmesh),tmesh),tmesh)));
if ( CGAL::abs(angle)<100 )
is_constrained[e]=true;
}
}
//remesh
PMP::isotropic_remeshing(
faces(tmesh),
target_edge_length,
tmesh,
PMP::parameters::number_of_iterations(nb_iter)
.edge_is_constrained_map(is_constrained) );
std::ofstream out("out.off");
out << tmesh;
return 0;
}