I am using GEOS 3.6.2 to compute an intersection between two polygons. I was able to construct my polygons, but when I try to compute the intersection it won't work.
Compiling my program in Debug mode, I get the error message:
The inferior stopped because it received a signal from the operating
system.
Signal name : SIGSEG
Signal meaning : Segmentation fault
Any idea where I'm wrong?
Here is my code:
#include <geos/geom/Polygon.h>
#include <geos/geom/LinearRing.h>
#include <geos/geom/CoordinateSequenceFactory.h>
#include <geos/geom/GeometryFactory.h>
#include <geos/geom/Geometry.h>
#include <geos/operation/overlay/OverlayOp.h>
#include <iostream>
#include <array>
////////////////////////////////////////////////////////////////////////////////
geos::geom::Polygon* MakePoly(std::vector<std::vector<int>> const& polyCoords)
{
geos::geom::GeometryFactory* factory = geos::geom::GeometryFactory::create().get();
geos::geom::CoordinateSequence* temp = factory->getCoordinateSequenceFactory()->create((std::size_t) 0, 0);
std::vector<std::vector<int>>::const_iterator it_x = polyCoords.begin();
int size = it_x->size();
for (int i=0; i<size; i++)
{
temp->add(geos::geom::Coordinate(polyCoords[0][i], polyCoords[1][i]));
}
geos::geom::LinearRing *shell=factory->createLinearRing(temp);
//NULL in this case could instead be a collection of one or more holes
//in the interior of the polygon
return factory->createPolygon(shell,NULL);
}
////////////////////////////////////////////////////////////////////////////////
int main()
{
// Create geometry.
std::vector<std::vector<int>> polyCoords1 = {
{1, 1, 2, 2, 1, 1, 4, 5, 4, 1},
{1, 2, 2, 4, 4, 5, 5, 3, 1, 1}
};
geos::geom::Polygon* poly1 = MakePoly(polyCoords1);
std::vector<std::vector<int>> polyCoords2 = {
{4, 4, 6, 6, 4},
{1, 5, 5, 1, 1}
};
geos::geom::Polygon* poly2 = MakePoly(polyCoords2);
// Actually perform the operation.
geos::operation::overlay::OverlayOp intersection(poly1, poly2);
// Extracting the geometry of the intersection (position of the error).
geos::geom::Geometry* intersectionGeo = intersection.getResultGeometry( geos::operation::overlay::OverlayOp::OpCode::opINTERSECTION );
std::cout<<intersectionGeo->getArea()<<std::endl;
}
The problem in your code is getting the GeometryFactory pointer.
geos::geom::GeometryFactory::create() returns a smart pointer (std::unique_ptr) so after this line:
geos::geom::GeometryFactory* factory = geos::geom::GeometryFactory::create().get();
The unique_ptr returned by create is disposed.
Change that line with:
geos::geom::GeometryFactory::Ptr factory = geos::geom::GeometryFactory::create();
And the code works.
Related
I'm newer to C++.
I've written the following line in a test function inside a standard VS2019 test project:
auto minAndMaxYards = std::minmax_element(simResults.begin(), simResults.end());
It yields both C2039 and C3861 errors for the minmax_element function even though intellisense recognizes it as a member of std, and I can peek its definition. I can't figure out what I'm missing. I've included the algorithm file as well at the top of the test project.
Is there a project setting that I don't have right?
Full error text:
C2039 'minmax_element': is not a member of 'std'
C3861 'minmax_element': identifier not found
Edit, including code in case it helps
#include <algorithm>
#include "pch.h"
#include "CppUnitTest.h"
#include "Playbook.h"
#include "PlaySim.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
std::string output;
using std::vector;
namespace FootballDynastyV20UnitTest
{
TEST_CLASS(PlaybookIO)
{
public:
TEST_METHOD(setAndGetPlayblookName)
{
Playbook testPlays;
string testName = "testPlays";
testPlays.setName(testName);
string name = testPlays.getName();
Assert::IsTrue(name == testName);
}
TEST_METHOD(addPlayIncrementsPlayNum)
{
Playbook testPlays;
string playName = "Play1";
int numDLine = 4;
int numLB = 3;
vector<int> playerPos = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19 };
vector<int> playerStance = { 2, 1, 0, 0, 1, 2, 2, 3, 2, 3, 3 };
vector<int> playerBlitzGaps = { 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0 };
testPlays.setName("testPlays");
testPlays.addPlay(playName, numDLine, numLB, playerPos, playerStance, playerBlitzGaps);
Assert::IsTrue(testPlays.getNumPlays() == 1);
}
TEST_METHOD(saveAndLoadPlayblook)
{
Playbook testPlays;
Playbook testPlaysLoad;
string playName = "Play1";
int numDLine = 4;
int numLB = 3;
vector<int> playerPos = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 19 };
vector<int> playerStance = { 2, 1, 0, 0, 1, 2, 2, 3, 2, 3, 3 };
vector<int> playerBlitzGaps = { 0, 3, 0, 0, 3, 0, 0, 0, 0, 0, 0 };
testPlays.setName("testPlays");
testPlays.addPlay(playName, numDLine, numLB, playerPos, playerStance, playerBlitzGaps);
testPlays.save();
testPlaysLoad.load(testPlays.getName());
Assert::IsTrue(testPlays == testPlaysLoad);
}
};
TEST_CLASS(PlaySimTesting)
{
public:
TEST_METHOD(playSimReturnsYdsGainedBetweenNegative10And40)
{
PlaySim newPlay;
int numSims = 2000;
int lwrBound = -10;
int uprBound = 40;
vector<int> simResults;
for (int i = 0; i < numSims; i++)
{
newPlay.Run();
simResults.push_back(newPlay.GetYds());
}
auto minAndMaxYards = std::minmax_element(simResults.begin(), simResults.end());
int actualMin = *minAndMaxYards.first;
int actualMax = *minAndMaxYards.second;
int yds = newPlay.GetYds();
Assert::IsTrue((actualMin >= lwrBound) && (actualMax <= uprBound));
}
};
}
Move #include "pch.h" to the top of the file. When using precompiled headers, the compiler ignores everything above this line. In your example, that would be #include <algorithm>, that's why std::minmax_element is not found.
I'm new with C++ and VTK. I'm trying to get cells ID into a rectilinearGrid basic example. I'm using this code, but the compiler say that is wrong with the error that I wrote in comment
#include <vtkActor.h>
#include <vtkCamera.h>
#include <vtkFloatArray.h>
#include <vtkNamedColors.h>
#include <vtkNew.h>
#include <vtkPolyDataMapper.h>
#include <vtkProperty.h>
#include <vtkRectilinearGrid.h>
#include <vtkRectilinearGridGeometryFilter.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <array>
int main()
{
vtkNew<vtkNamedColors> colors;
std::array<int, 16> x = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
std::array<int, 16> y = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
std::array<int, 16> z = {
{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}};
// Create a rectilinear grid by defining three arrays specifying the
// coordinates in the x-y-z directions.
vtkNew<vtkFloatArray> xCoords;
for (auto&& i : x)
{
xCoords->InsertNextValue(i);
}
vtkNew<vtkFloatArray> yCoords;
for (auto&& i : y)
{
yCoords->InsertNextValue(i);
}
vtkNew<vtkFloatArray> zCoords;
for (auto&& i : z)
{
zCoords->InsertNextValue(i);
}
// The coordinates are assigned to the rectilinear grid. Make sure that
// the number of values in each of the XCoordinates, YCoordinates,
// and ZCoordinates is equal to what is defined in SetDimensions().
//
vtkNew<vtkRectilinearGrid> rgrid;
rgrid->SetDimensions(int(x.size()), int(y.size()), int(z.size()));
rgrid->SetXCoordinates(xCoords);
rgrid->SetYCoordinates(yCoords);
rgrid->SetZCoordinates(zCoords);
vtkCell* GetCell(vtkRectilinearGrid * rgrid, int i, int j, int k) //I SHOULD INSERT IN HERE ";" FOR
{ //CLOSING THE STATEMENT. BUT IN
int dims[3]; //THIS WAY THE FUNCTION PARAMETER
rgrid->GetDimensions(dims); // BEHIND WOULDN'T BE CONNECTED.
if (i < 0 || i > dims[0] - 1 ||
j < 0 || j > dims[1] - 1 ||
k < 0 || k > dims[2] - 1)
{
return NULL; // out of bounds!
}
int pos[3];
pos[0] = i;
pos[1] = j;
pos[2] = k;
vtkIdType id;
id = vtkStructuredData::ComputeCellId(dims, pos);
return rgrid->GetCell(id);
};
// Extract a plane from the grid to see what we've got.
vtkNew<vtkRectilinearGridGeometryFilter> plane;
plane->SetInputData(rgrid);
plane->SetExtent(0, 46, 16, 16, 0, 43);
vtkNew<vtkPolyDataMapper> rgridMapper;
rgridMapper->SetInputConnection(plane->GetOutputPort());
vtkNew<vtkActor> wireActor;
wireActor->SetMapper(rgridMapper);
wireActor->GetProperty()->SetRepresentationToWireframe();
wireActor->GetProperty()->SetColor(colors->GetColor3d("Black").GetData());
// Create the usual rendering stuff.
vtkNew<vtkRenderer> renderer;
vtkNew<vtkRenderWindow> renWin;
renWin->AddRenderer(renderer);
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(renWin);
renderer->AddActor(wireActor);
renderer->SetBackground(1, 1, 1);
renderer->ResetCamera();
renderer->GetActiveCamera()->Elevation(30.0);
renderer->GetActiveCamera()->Azimuth(15.0);
renderer->GetActiveCamera()->Zoom(1.0);
renderer->SetBackground(colors->GetColor3d("Beige").GetData());
renWin->SetSize(600, 600);
// interact with data
renWin->Render();
iren->Start();
return EXIT_SUCCESS;
}
How could be fixed?
UPDATE 1: I have inserted an image of the compiling error. Should be inserted ";" for closing the statement before {}
UPDATE 2: the exact error is
Errore (attivo) E0065 expected ';' RGrid C:\vtk\VTK-8.2.0\Examples\DataManipulation\Cxx\RGrid.cxx 73
I'm using Visual Studio. I have tried to drop the last ";" but nothing change
UPDATE 3: I have uploaded all the code
You have defined your GetCell function inside the body of the main function, which is not allowed in C++. Only a declaration would be allowed inside the body, hence the compiler expects a semicolon after the function header.
Move the whole GetCell function block outside the main function. If that leads to problems you cannot solve ask another question about them.
I am trying to reset 2D array to its original form after it's been sorted with a bubble sort. I need to reset it back to what it was before sorting. How do I do it? In case you have a question why an array is global. It's a school assignment and that's how our professor wants us to do it.
Here is my program:
#include<iostream>
using namespace std;
const int NUM_COLS=4;
const int NUM_ROWS=5;
int array[NUM_ROWS][NUM_COLS]={{5, 3, 2, 16},
{9, 8, 10, 17},
{4, 7, 11, 18},
{2, 5, 9, 12},
{7, 9, 4, 10}};
it sorts an array with bubbleSort
void bubbleSort(int row, int col){}
it is display array function header
void displayArray(){}
and here is main function
int main(){
cout<<"original array"<<endl;
displayArray();
bubbleSort(NUM_ROWS-1, NUM_COLS);
cout<<"\nbubble sort"<<endl;
displayArray();
reset();
displayArray();
return 0;
}
Now I need to reset an array back to original. I did this but it doesn't work.
void reset(){
int array[NUM_ROWS][NUM_COLS]={{5, 3, 2, 16},
{9, 8, 10, 17},
{4, 7, 11, 18},
{2, 5, 9, 12},
{7, 9, 4, 10}};
}
Your reset is declaring a new array (and doing nothing with it). You can't assign (=) C style arrays, so you will need something that looks different. If you can use std::array instead, you could assign in reset.
#include <array>
const int NUM_COLS=4;
const int NUM_ROWS=5;
std::array<std::array<int, NUM_ROWS>, NUM_COLS> values = {
{5, 3, 2, 16},
{9, 8, 10, 17},
{4, 7, 11, 18},
{2, 5, 9, 12},
{7, 9, 4, 10}};
// Other code probably remains unchanged
void reset() {
values = {
{5, 3, 2, 16},
{9, 8, 10, 17},
{4, 7, 11, 18},
{2, 5, 9, 12},
{7, 9, 4, 10}};
}
At which point you notice that you've got your bounds the wrong way round, and it should either be
const int NUM_COLS=5;
const int NUM_ROWS=4;
or a differently shaped array initialiser.
void reset(){
static int original[NUM_ROWS][NUM_COLS]={{5, 3, 2, 16},
{9, 8, 10, 17},
{4, 7, 11, 18},
{2, 5, 9, 12},
{7, 9, 4, 10}};
for (int i = 0; i < NUM_ROWS; i++)
memcpy(array[i], original[i], NUM_COLS * sizeof(int));
}
Not the prettiest thing, but this should work. Since that's how your professor wants you to do it, go for it ¯\_(ツ)_/¯
As I said in a comment, the easiest way to assign arrays is to wrap them in a structure. Voilà, suddenly C++ develops abilities it didn't even know it had inherited from C and copies arrays!1 Even nested, multi-dimensional arrays!
#include <iostream>
#include <iomanip>
#include <algorithm>
using namespace std;
const int NUM_COLS=4;
const int NUM_ROWS=5;
// Define a struct (i.e., a class with all public members)
// which has just a single member, the array. Note that this is
// only a *type* declaration, no object is created yet.
struct arrT
{
int array [NUM_ROWS][NUM_COLS];
};
// object creation.
arrT workArr;
void reset()
{
// The initialization value is hidden inside the function.
// static variables are initialized only once, for constant
// data at compile time.
static const arrT oriArr
{
{ {5, 3, 2, 16},
{9, 8, 10, 17},
{4, 7, 11, 18},
{2, 5, 9, 12},
{7, 9, 4, 10}
}
};
workArr = oriArr; // simple default assignment of structs
}
// The parameters are redundant.
void stdSort(int /*row*/, int /*col*/)
{
// Sort the 2D array as a one-dimensional sequence
// (which the elements are in memory).
// The algorithm expects iterators to the first and
// one-after-the-last elements in the sequence. Pointers
// to the elements in an array are perfectly good iterators.
std::sort(&workArr.array[0][0], &workArr.array[NUM_ROWS-1][NUM_COLS]);
}
void displayArray()
{
// The top-level elements of a 2D array are the rows...
for(auto &row: workArr.array)
{
// ... and the elements of the rows are ints.
// Note how the
// dimensions are known from the class declaration.
for(auto &el: row)
{
cout << setw(4) << el;
}
cout << "\n";
}
}
int main(){
cout << "Work array before initialization:\n";
displayArray();
reset(); // before, the values of the global array are 0.
cout<<"\nWork array after init:\n";
displayArray();
stdSort(NUM_ROWS, NUM_COLS);
cout<<"\nWork array after std sort"<<endl;
displayArray();
reset();
cout << "\nWork array after reset\n";
displayArray();
return 0;
}
1 Arrays are the only example I know of off the cuff where the memberwise assignment of the generated default assignment operator can assign a type which does not have a standalone assignment operator (which is the exact reason we jump through this hoop). Are there others?
I have the following SIMD code trying to run in vs2013. It can be well compiled but cannot run. Anyone knows why?
#include <cstdio>
#include <xmmintrin.h>
int main()
{
const size_t num = 7;
float a[num] = { 1, 2, 3, 4, 5, 6, 7 };
float b[num] = { 1, -1, -2, 1, -3, -2, 5 };
float c[num];
__m128 A, B, C;
A = _mm_load_ps(&a[0]); // <== crash here.
B = _mm_load_ps(&b[0]);
C = _mm_add_ps(A, B);
_mm_store_ps(&c[0], C);
return 0;
}
The address being loaded from or stored to using these intrinsics needs to be 16 byte aligned (divisible by 16). See
https://msdn.microsoft.com/en-us/library/zzd50xxt(v=vs.90).aspx
You should declare the variables a,b and c like this:
__declspec(align(16)) float a[num] = { 1, 2, 3, 4, 5, 6, 7 };
I can't seem to get the implementation of my member list correct. I want to DEFAULT initialize my Set members nyX and nyY, however I keep getting an error.
class Location
{
public:
vector<int> nyXv = { 0, 1, 2, 3, 4, 5};
vector<int> nyYv = { 0, 1, 2, 3, 4, 5 };
Set nyX(vector<int>);
Set nyY(vector<int>);
Location();
~Location();
};
Location::Location()
:nyX(nyXv), nyY(nyYv)
{
}
Look at this example
You can initialize you vectors like this:
class Location
{
public:
vector<int> nyXv;// = { 0, 1, 2, 3, 4, 5};
vector<int> nyYv;// = { 0, 1, 2, 3, 4, 5 };
///...
Location();
~Location();
};
static const int arrX[] = {0, 1, 2, 3, 4, 5};
static const int arrY[] = {0, 1, 2, 3, 4, 5};
Location::Location()
:nyXv(arrX, arrX + sizeof(arrX) / sizeof(arrX[0]) )
,nyYv(arrY, arrY + sizeof(arrY) / sizeof(arrY[0]))
{
}
P.S. Of course there are many ways to improve this code but it should give you an idea