PS::Simplification with 3d points - cgal

Im trying to simplify 3d polylines using CGAL::Simplify, is a terrain so the elevation does not matter for the simplification but I need to carry them because I need them on simplified polylines. The polylines can be open or closed (polygon).
The problem occurs when I try to call PS::simplify with 3d points. I checked and it work ok with 2d points. The funny is that it accept 3d points for parameters begin and end of the polyline but do not accept for the back_inserter parameter.
Is there any version of simplify that work completely with 3d points or I´m missing something?
on the code:
PS::simplify(P1.begin(), P1.end(), CostSquare(), Stop(0.5), std::back_inserter(Result),Closed);
Templates and parametes definitions:
namespace PS = CGAL::Polyline_simplification_2;
typedef CGAL::Exact_predicates_exact_constructions_kernel Epic;
typedef CGAL::Projection_traits_xy_3<Epic> K;
typedef CGAL::Polygon_2<K> Polygon_2;
Polygon_2_2 P1;
std::deque<Point_2> Result;
typedef K::Point_2 Point_2;
Thank you
Carlos A. Rabelo

Related

How to fix 'CGAL::Precondition_exception' when constructing Polygon_set_2

I'm using the CGAL library in a a Visual Studio project.
I'm trying to create a polygon_set_2 composed of polygons with holes. I run into an exception when creating the polygon_set_2 even when just using simple polygons.
Typedefs:
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::Point_2 CGALPoint;
typedef CGAL::Polygon_2<K> CGALInnerPolygon;
typedef CGAL::Polygon_set_2<K> CGALMultiPolygon;
Problem code:
CGALInnerPolygon cgalpoly;
cgalpoly.push_back(CGALPoint(0, 0));
cgalpoly.push_back(CGALPoint(1, 1));
cgalpoly.push_back(CGALPoint(1, 0));
CGALMultiPolygon multipolygon;
multipolygon.insert(cgalpoly);
I get an exception on the insert call. Output for the exception is:
Exception thrown at 0x75112CF2 in XXX.exe: Microsoft C++ exception: CGAL::Precondition_exception at memory location 0x00191AF0
It was actually a combination of two things. First the polygon points much be counterclockwise as sloriot mentioned. To fix for this in the general case the following code was added:
if (cgalpoly.is_clockwise_oriented())
{
cgalpoly.reverse_orientation();
}
Secondly, the the Polygon_set_2 must use an exact construction kernel:
typedef CGAL::Exact_predicates_exact_constructions_kernel K;

CGAL Voronoi Diagram for Segments

I have used a CGAL Segment_Delaunay_graph to create a voronoi diagram for a collection of line segments. I would like to extract the edges of the Segment_Delaunay_graph which correspond to the voronoi cells. There are methods draw_dual() and draw_skeleton() for this purpose, but both include some additional edges that I don't want to retain (and draw_skeleton removes some edges that I do want to retain).
Here is an image to show the issue:
example voronoi diagram
The black lines are inputs. They are typically groups of several segments connected end-to-end to form longer lines, although each segment is input to the Segment_Delaunay_graph individually like this:
s 1677850.1951146198 466276.4198628192 1784307.2726912862 466276.4198628192
s 1784307.2726912862 466276.4198628192 1784307.2726912862 567677.3831007502
s 1784307.2726912862 567677.3831007502 1677850.1951146198 567677.3831007502
The red and blue lines are output by draw_dual(). I want to retain the red lines which represent voronoi cell boundaries around the connected input lines, but I do not want to keep the blue lines. Is is possible to filter out the unwanted edges based on information stored in the Segment_Delaunay_graph? If so, how?
Some sample code:
#include <iostream>
#include <fstream>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Segment_Delaunay_graph_filtered_traits_2.h>
#include <CGAL/Segment_Delaunay_graph_2.h>
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef CGAL::Segment_Delaunay_graph_filtered_traits_2<K> Gt;
typedef CGAL::Segment_Delaunay_graph_2<Gt> SDG2;
using namespace std;
int main()
{
//read line segments from input file
string inFile = "example-a.in";
ifstream ifs(inFile);
SDG2 sdg;
SDG2::Site_2 site;
std::vector<SDG2::Site_2> sites;
while (ifs >> site) {
sites.push_back(site);
}
ifs.close();
//add line segments to diagram
sdg.insert(sites.begin(), sites.end(), CGAL::Tag_true());
//save voronoi edges to a file
string outFile = "example-a.out";
ofstream ofs(outFile);
sdg.draw_dual(ofs);
ofs.close();
}
I observe the red lines you want to keep. Are they the edges that far away to the sites that are not the junction sites? You can set a distance threshold d, if the distance between the edge to its closest site is smaller than d and the site is not a junction, then remove this edge.

Compiling GLSL written for OpenGL ES versions to Vulkan

My question is similar to this one but part of the (useful) given answer isn't compatible with compiling GLSL for vulkan based on OpenGL ES ESSL 3.10.
In order to use a separate section of the push constant memory in the vertex shader and the fragment shader, the suggested solution is to use layout(offset = #) before the first member of the push constant structure.
Attempting to do this in GLSL ES 310 code leads to the error "'offset on block member': not supported with this profile: es".
Is there a supported way to declare such an offset that is compatible with es?
The only workaround I've found is to declare a bunch of dummy variables in the fragment shader. When I do so, I get validation layer errors if I don't declare the full range of the fragment shader's push constant buffer in VkPipelineLayoutCreateInfo. After fixing that, I get validation layer warnings about "vkCreatePipelineLayout() call has push constants with overlapping ranges".
Obviously I can ignore warnings, but if there's a tidier solution, then that would be much more preferable.
Simple example, this compiles successfully with VulkanSDK\1.0.13.0\Bin\glslangValidator.exe:
#version 430
#extension GL_ARB_enhanced_layouts: enable
layout(std140, push_constant) uniform PushConstants
{
layout(offset=64) mat4 matWorldViewProj;
} ubuf;
layout(location = 0) in vec4 i_Position;
void main() {
gl_Position = ubuf.matWorldViewProj * i_Position;
}
Whereas this does not:
#version 310 es
#extension GL_ARB_enhanced_layouts: enable
layout(std140, push_constant) uniform PushConstants
{
layout(offset=64) mat4 matWorldViewProj;
} ubuf;
layout(location = 0) in vec4 i_Position;
void main() {
gl_Position = ubuf.matWorldViewProj * i_Position;
}
Converting all my 310 ES shader code to 430 would solve my problem, but that wouldn't be ideal. GL_ARB_enhanced_layouts doesn't apply to 310 ES code, so my question is not about why it doesn't work, but rather, do I have any options in ES to achieve the same goal?
I would consider this an error in the GLSL compiler.
What's happening is this. There are some things which compiling GLSL for Vulkan adds to the language, as defined by KHR_vulkan_glsl. The push_constant layout, for example, is explicitly added to GLSL syntax.
However, there are certain things which it does not add to the language. Important to your use case is the ability to apply offsets to members of uniform blocks. Oh yes, KHR_vulkan_glsl uses that information when building the shader's block layout. But the grammar that allows you to say layout(offset=#) is defined by GLSL, not by KHR_vulkan_glsl.
And that grammar is not a part of any version of GLSL-ES. Nor is it provided by any ES extension I am aware of. So you can't use it.
I would say that the reference compiler should, when compiling a shader for Vulkan, either fail to compile any GLSL-ES-based version, or silently ignore any version and extension declarations, and just assume desktop GLSL 4.50.
As for what you can do about it... nothing. Short of hacking that solution into the compiler yourself, your primary solution is to write your code against versions of desktop OpenGL. Like 4.50.
If you compile SPIR-V for Vulkan there is a "VULKAN" define set in your shaders (see GL_KHR_VULKAN_glsl), so you could do something like this:
#ifdef VULKAN
layout(push_constant) uniform pushConstants {
vec4 (offset = 12) pos;
} pushConstBlock;
#else
// GLES stuff
#endif

Issue precision CGAL's Delaunay triangulation

I am having an issue that is probably due to the mismatch between the precision of a double and the infinite precision given in CGAL, but I cannot seem to solve it, and do not see anyway to set a tolerance.
I input a set of points (initially the locations are doubles).
When the points are aligned horizontally on the upper part (and only happens there) I sometimes (not always) get an issue of too many triangles (with a really small area, almost 0) being generated: see image
(*notice in the upper section, how there is a line that seems to be thicker than the rest, because there are at least 3 triangles there).
This is what I am doing in my code, I tried to set the kernel to handle the imprecision of doubles:
typedef CGAL::Simple_cartesian<double> CK;
typedef CGAL::Filtered_kernel<CK> K;
//typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
typedef K::FT FT;
typedef K::Point_2 Point;
typedef K::Segment_2 Segment;
typedef CGAL::Polygon_2<K> Polygon_2;
typedef CGAL::Triangulation_vertex_base_with_info_2<unsigned long, K> Vb2;
typedef CGAL::Triangulation_data_structure_2<Vb2,Fb> Tds2;
typedef CGAL::Delaunay_triangulation_2<K,Tds2> Delaunay;
std::vector<std::vector<long> > Geometry::delaunay(std::vector<double> xs,std::vector<double> ys){
std::vector<Point> points;
std::vector<unsigned long> indices;
points.resize(xs.size());
indices.resize(xs.size());
for(long i=0;i<xs.size();i++){
indices[i]=i;
points[i]=Point(xs[i],ys[i]);
}
std::vector<long> idAs;
std::vector<long> idBs;
Delaunay dt;
dt.insert( boost::make_zip_iterator(boost::make_tuple( points.begin(),indices.begin() )),boost::make_zip_iterator(boost::make_tuple( points.end(),indices.end() ) ) );
for(Delaunay::Finite_edges_iterator it = dt.finite_edges_begin(); it != dt.finite_edges_end(); ++it)
{
Delaunay::Edge e=*it;
long i1= e.first->vertex( (e.second+1)%3 )->info();
long i2= e.first->vertex( (e.second+2)%3 )->info();
idAs.push_back(i1);
idBs.push_back(i2);
}
std::vector<std::vector<long> > result;
result.resize(2);
result[0]=(idAs);
result[1]=(idBs);
return result;
}
I am completely new to CGAL, and this code is something that I have been able to put together after a lot of looking up in web pages in the last 2 days. So if there is something else that might be improved, please, do not hesitate to mention it, the sintaxis of CGAL is not really straightforward.
*the code works perfectly for random points, and 70% of the times even for points that are aligned, but the other 30% worries me.
THE QUESTION IS, how can I set a tolerance, so CGAL does not generate triangles on top of points that are almost almost aligned??, or is there a better kernel for this? (as you see I tried also the Exact_predicates_inexact_constructions_kernel, but it is even worst).

CGAL 4.7: Arrangement insert(arr,begin,end) crashes

I'm trying to do the aggregate insertion of x-monotone polylines, but I get the following error:
terminate called after throwing an instance of 'CGAL::Precondition_exception'
what(): CGAL ERROR: precondition violation!
Expr: i != INVALID_INDEX
File: /home/vladimir/lib-cgal/include/CGAL/Arr_polycurve_basic_traits_2.h
Line: 727
And have no clue why it happens. Do I miss something? Is my input wrong? Or is it a bug? Here is a code snippet resulting in this behavior:
#include <vector>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arr_segment_traits_2.h>
#include <CGAL/Arr_polyline_traits_2.h>
#include <CGAL/Arrangement_2.h>
typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel;
typedef Kernel::Point_2 Point_2;
typedef CGAL::Arr_segment_traits_2<Kernel> Segment_traits_2;
typedef CGAL::Arr_polyline_traits_2<Segment_traits_2> Geom_traits_2;
typedef CGAL::Arrangement_2<Geom_traits_2> Arrangement_2;
int main()
{
Arrangement_2 arr;
std::vector<Geom_traits_2::X_monotone_curve_2> segments;
{
auto ctor = arr.geometry_traits()->construct_x_monotone_curve_2_object();
typedef std::vector<Point_2> Line;
std::vector<Line> lines = {
{{0,0}, {8,0}},
{{2,0}, {7,0}},
{{4,2}, {6,3}},
{{1,1}, {3,0}, {5,0}},
};
for (auto &line: lines) {
segments.push_back(ctor(line.begin(), line.end()));
}
}
insert(arr, segments.begin(), segments.end());
return 0;
}
CGAL version I'm using is 4.7, but I have tried it with 4.5.2 and the lates git version (81d638341) with the same result.
The lines are intersecting, but that should be fine as I understand. I have observed that changing {{1,1}, {3,0}, {5,0}} to {{2,1}, {3,0}, {5,0}} results in no error. And splitting {{1,1}, {3,0}, {5,0}} into two segments {{1,1}, {3,0}}, {{3,0}, {5,0}} results in no error as well.
I have also noticed another thread (link) with similar problem which was fixed, but I don't see this fix in the version 4.7. Probably it's fixed somewhere else in the code, or perhaps this fix got lost somehow.? Anyway, it looks like it's not related to my problem, but one never knows.
I was able to reproduce the problem and at first glance it looks like a bug. We are looking into it, but for now you have 2 options to work around the problem:
1. Use incremental insertion. The incremental insertion is based on a completely different algorithm.
2. Break each polyline into segments and construct an arrangement of segments instead of an arrangement of polylines. I've tested it with the minimal example that produces the problem you provided (that you, by the way for that) and it works fine.
BW, the link you mentioned is unrelated.