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.
Related
Using this https://github.com/antlr/grammars-v4/tree/master/cpp antlr grammar Im trying to parse C++ code. Below is the same visitor class I'm using, I don't have much visitor function implemented,
#include <iostream>
#include <antlr4-runtime.h>
#include "parser/CPP14Lexer.h"
#include "parser/CPP14BaseVisitor.h"
#include "parser/CPP14Parser.h"
#include "parser/CPP14Visitor.h"
class TREEVisitor : public CPP14BaseVisitor {
public:
virtual antlrcpp::Any TREEVisitor::visitAdditiveExpression(
CPP14Parser::AdditiveExpressionContext *ctx) override
{
std::cout << "AddExpr : " << ctx->getText() << std::endl;
std::vector<CPP14Parser::MultiplicativeExpressionContext *> mulpExprCtx =
ctx->multiplicativeExpression();
for (CPP14Parser::MultiplicativeExpressionContext *mulpExprLp : mulpExprCtx)
{
std::vector<CPP14Parser::PointerMemberExpressionContext *> ptrMbrExprCtx =
mulpExprLp->pointerMemberExpression();
// ptrMbrExprCtx->pointerMemberExpression()->castExpression()->unaryExpression();
// Different parts of an expression
for (CPP14Parser::PointerMemberExpressionContext *ptrMbrExprLp : ptrMbrExprCtx)
{
std::cout << "=> " << ptrMbrExprLp->getText() << std::endl;
}
}
return visitChildren(ctx);
}
};
int main(int argc, char *argv[]) {
std::ifstream stream;
stream.open(argv[1]);
antlr4::ANTLRInputStream input(stream);
CPP14Lexer lexer(&input);
antlr4::CommonTokenStream tokens(&lexer);
CPP14Parser parser(&tokens);
antlr4::tree::ParseTree *tree = parser.translationunit();
// Visitor
auto *visitor = new TREEVisitor();
visitor->visit(tree);
return 0;
}
Im trying to parse the following C++ code,
int ii = a + b - getLength() * 10 / 1;
What I'm trying to achieve here is to get all of the variables that are used to initilize the variable i and their signs. Something like below, where i can relate each sign to the values/variables(for example to know that + as after a.
a
+
b
-
getLength()
*
10
/
1;
So far I can only get an output as follow,
AddExpr : a+b-c*10/1
=> a
=> b
=> getLength()
=> 10
=> 1
I don't seem to be able to get the signs between each operation.
I seem to have something related to the signs in that equation, I had only Star and Mod.
tree::TerminalNode* startTn = mulpExprLp->Star();
So I tried to change the grammar file to get other signs as well. While that gave me the signs in that equation but again... I wasn't ablel to know the position of each sign in the equation.
multiplicativeExpression:
pointerMemberExpression (
(Star | Div | Mod | Plus | Minus) pointerMemberExpression
)*;
I hope I could describe the problem clearly. I basically want to read the each part of an equation and know what is the position of each sign.
Thanks,
Alex
It looks like you need a better understanding of the structure of your parse tree.
I would suggest going back to the original grammar (there are many problems with your multiplcativeExpression, mostly around it not building a proper parse tree.
Viewing the graphical version of your parse tree should be quite useful. This page gives a brief intro to setting up a grun alias to use TestRig. It’s usually a good idea to “play around” a bit with grun and various input to gain a better understanding of what ANTLR produces (token streams, parse trees, etc.) for your grammar.
Take a look at the documentation and how to run the TestRig utility with the -gui command line option. This will give you a graphical representation of your parse tree. Your immediate issue is that, since you only have a visitor for additiveExpression, it won’t include the sub tree for the mutiplicativeExpression that will hold the structure for multiplication and division.
Also, since you’re not finding the operations you need to take a closer look at the cpp14parser::AdditiveExpressionContext generated for your additiveExpression. The operator(s) should be available at one of the indices of your children nodes (the rule is written to allow multiple addition/subtraction in a single context, so they’ll probably be available in some list/array structure (sorry, not intimately familiar with what ANTLR generates for C++)
BTW, you may find that, for your purposes, a listener is easier to use than a visitor. With Listeners a ParseTreeWalker takes care of walking the tree and calling back to your code as nodes are encountered. With Visitors, it’s up to you to navigate the parse Tree (they can be useful when you need more flexibility, and a bit easier to handle things if you want a value returned from visiting a node, but I find Listeners much simpler for most use cases)
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
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).
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.
In solving competitive programming problem what are the things we need to consider to solve a problem in time efficient way?
For instance, in one problem, Project Euler Multiples of 3 and 5 Code runs in O(n^2). This is considering the loop for taking the test cases.
Questions:
Why does the code time out in this problem?
How can I make my code efficient?
The description of the question is in the link.
#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
int t, n;
int n1,n2;
int mul3, mul5, sum=0,sum3=0,sum5=0;
cin>> t;
while(t--){
cin>>n;
sum=0;
sum5=0;
sum3=0;
if(n%3==0)
n1=n/3-1;
else
n1=n/3;
if(n%5==0)
n2=n/5-1;
else
n2=n/5;
for(int i=0;i<=n1;i++){
if(i<=n2){
mul5= i*5;
sum5+=mul5;
}
mul3=i*3;
if((mul3%5)!=0)
sum3+=mul3;
sum = sum3+sum5;
}
cout << sum << endl;
}
system("PAUSE");
return 0;
}
You don't need to iterate over all numbers and you definitely can't afford to perform n^2 operations for n=10^9. The correct solutions requires a little knowledge of number theory and of the count of numbers divisible by a given value. Can you figure out a way to compute the count of numbers divisible by 5 up to X? Try to do that with constant complexity. Then do something similar for the numbers divisible by 3 and apply the inclusion-exclusion principle.
Please note: optimizing your code no matter how well will only improve its performance marginally. Changing the algorithm on the other hand may change its complexity orders of magnitude.
Maybe having a little look here will help you get a O(1) solution Inclusion–exclusion principle.
For this problem set A consists of numbers divisible by 3, set B consists of numbers divisible by 5. And A∩B consists of numbers that are divisible by both 3 and 5. So ,
A={3,6,9,...,999}
This forms an arithmetic series. You can find the sum of this using standard formula. Do the same for other 2 sets and you are done.