So I have decided to implement an algorithm based on vectors to solve the Closest pair of points problem (2D). It seems to work with easy cases like
1.2 4.5
2.4 1.2
3.3 1.1
4.4 4.4
7.7 1.1
1.1 2.1
8.6 1.9
3.3 9.0
And the output is correct (for this case it is 0.90554), but somebody has checked my code and said that there is an invalid memory reference somewhere. I've been really struggling with this piece of code but I've give up, there is no way to find what is wrong (bc the cases I try work!).
I would really appreciate if somebody could enlighten me!
Thanks in advance!
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
struct Point { double x, y; };
bool compareX (Point p, Point q) { return p.x < q.x; }
bool compareY (Point p, Point q) { return p.y < q.y; }
float dist(Point p1, Point p2) {
return sqrt((p1.x - p2.x)*(p1.x - p2.x) + (p1.y - p2.y)*(p1.y - p2.y));
}
double min_dist (vector<Point> pointsX, vector<Point> pointsY, int n) {
// BASE CASE.
if (n <= 3) {
double min = __DBL_MAX__;
for (int i = 0; i < n; ++i)
for (int j = i +1 ; j < n; ++j)
if (dist(pointsX[i], pointsX[j]) < min)
min = dist(pointsX[i], pointsX[j]);
return min;
}
// Step 1: Find the middle point.
int mid = n/2;
Point mid_point = pointsX[mid];
// Step 2: Divide the set in two equal-sized parts (left and right).
vector<Point> pointsY_left;
vector<Point> pointsY_right;
vector<Point> pointsX_left;
vector<Point> pointsX_right;
for (int i = 0; i < n; ++i) {
if (i < mid and pointsY[i].x <= mid_point.x) pointsY_left.push_back(pointsY[i]);
else pointsY_right.push_back(pointsY[i]);
}
for (int i = 0; i < n; ++i) {
if (i < mid and pointsX[i].x <= mid_point.x) pointsX_left.push_back(pointsX[i]);
else pointsX_right.push_back(pointsX[i]);
}
// Step 3: Calculate the smaller distance at left and right parts recursively.
double d_left = min_dist(pointsX_left, pointsY_left, mid);
double d_right = min_dist(pointsX_right , pointsY_right, n - mid);
// Let d be the minimal of the 2 distances.
double d = min (d_left, d_right);
// Eliminate points that are farther than d <=> Create a strip that contains
// points closer than d.
vector<Point> strip;
for (int i = 0; i < n; ++i) if (abs(pointsY[i].x - mid_point.x) < d) strip.push_back(pointsY[i]);
// Scan the points from the strip and compute the dstances of each point to its 7 neighbours.
// Pick all points one by one and try the next points until the difference
// between y coordinates is smaller than d.
for (int i = 0; i < int(strip.size()); ++i)
for (int j = i + 1; j < int(strip.size()) and (strip[j].y - strip[i].y) < d; ++j)
if (dist (strip[i], strip[j]) < d)
d = dist(strip[i], strip[j]);
return d;
}
double closest(const vector<Point>& points) {
// Initial step: sort points accroding to their coordinates.
vector<Point> pointsX, pointsY;
pointsX = pointsY = points;
sort(pointsX.begin(), pointsX.end(), compareX);
sort(pointsY.begin(), pointsY.end(), compareY);
return min_dist (pointsX, pointsY, int(points.size()));
}
int main() {
cout.setf(ios::fixed);
cout.precision(5);
vector<Point> points;
double x, y;
while (cin >> x >> y) {
Point p = {x, y};
points.push_back(p);
}
cout << closest (points) << endl;
}
Looks like problem is in Step 2. You have two different conditions i < mid and pointsY[i].x <= mid_point.x and i < mid and pointsX[i].x <= mid_point.x, but in the following code you suppose these conditions are equal. Probably you should replace these conditions with just i < mid.
// Step 1: Find the middle point.
int mid = n/2;
Point mid_point = pointsX[mid];
// Step 2: Divide the set in two equal-sized parts (left and right).
vector<Point> pointsY_left;
vector<Point> pointsY_right;
vector<Point> pointsX_left;
vector<Point> pointsX_right;
for (int i = 0; i < n; ++i) {
if (i < mid and pointsY[i].x <= mid_point.x) pointsY_left.push_back(pointsY[i]);
else pointsY_right.push_back(pointsY[i]);
}
for (int i = 0; i < n; ++i) {
if (i < mid and pointsX[i].x <= mid_point.x) pointsX_left.push_back(pointsX[i]);
else pointsX_right.push_back(pointsX[i]);
}
P.S. You can simply use constructor of vector:
vector<Point> pointsY_left( pointsY.cbegin(), pointsY.cbegin() + mid );
vector<Point> pointsY_right( pointsY.cbegin() + mid, pointsY.cend() );
vector<Point> pointsX_left( pointsX.cbegin(), pointsX.cbegin() + mid );
vector<Point> pointsX_right( pointsX.cbegin() + mid, pointsX.cend() );
Related
So, here is the problem.
I am given the lengths of 3 sides of a triangle.
The program calculates the area of the given triangle using determinates.
I assume that one vertex of the triangle is in the (0,0) point and the 2nd one is in the (c,0), where c is the length of the longest side. So what would be the easiest way to get the 3rd vertices coordinates.
I tried cosine theorem to get the line equation the side is going through, but it is a bit off
I have the determination solver program if you need it down here:
float det(int n, float mat[3][3])
{
int d=0;
int c, subi, i, j, subj;
float submat[3][3];
if(n == 2) {
return( (mat[0][0] * mat[1][1]) - (mat[1][0] * mat[0][1]));
}
else{
for(c = 0; c < n; c++){
subi = 0;
for(i = 1; i < n; i++){
subj = 0;
for(j = 0; j < n; j++){
if (j == c){
continue;
}
submat[subi][subj] = mat[i][j];
subj++;
}
subi++;
}
d = d + (pow(-1 ,c) * mat[0][c] * det(n - 1 ,submat));
}
}
return d;
}
.
.
.
ans=det.det(3,coords)*0.5;
Example picture of the triangle constructed in GeoGebra:
I'm trying to do a normalization of data for a polinomial interpolation with perceptron, I'm using the following formula:
Where:
xi is a data point (x1, x2…xn).
x̄ is the sample mean.
s is the sample standard deviation.
and Z is my new value of input for the perceptron.
I'm programming in C ++, and plotting graph with freeglut.
My function for normalize:
vector<double> Perceptron::normalizar(double x) {
vector<double> aux;
aux.push_back(1.0);
for (unsigned i = 1; i < pesos.size(); i++) {
double t = (pow(x,i) - means[i]) / devianation[i];
aux.push_back(t);
}
return aux;
}
The problem is: before I did the normalization, the polynomial was converging to the points.
But after normalization, the polynomial is converging to other points, and I do not know where it is converging.
The formula for the polynomial would be as follows (with W being the weights of the perceptron):
So I used a mean formula for each value of x.
See the code:
void Perceptron::mean(Points P) { //P is a struct with all x and y values of the points.
means.clear(); //vector that stores the means
for (unsigned i = 0; i < weights.size(); i++) {
double m = 0;
for (unsigned j = 0; j < P.size(); j++) {
m += pow(P[i].x, i);
}
means.push_back(m / P.size());
}
}
void Perceptron::deviation(Points P) {
deviations.clear(); //vector that stores the deviations
for (unsigned i = 0; i < weights.size(); i++) {
double sd = 0;
for (unsigned j = 0; j < P.size(); j++) {
sd += pow(pow(P[j].x, i) - means[i], 2);
}
deviations.push_back(sqrt(sd / P.size()));
}
}
Here is my code for creating the hough accumulator for lines in image :
void hough_lines_acc(cv::Mat img_a_edges, std::vector<std::vector<int> > &hough_acc) {
for (size_t r = 0; r < img_a_edges.rows; r++) {
for (size_t c = 0; c < img_a_edges.cols; c++) {
int theta = static_cast<int> (std::atan2(r, c) * 180 / M_PI);
int rho = static_cast<int> ((c * cos(theta)) + (r * sin(theta)));
if (theta < -90) theta = -90;
if (theta > 89) theta = 89;
++hough_acc[abs(rho)][theta];
}
}
cv::Mat img_mat(hough_acc.size(), hough_acc[0].size(), CV_8U);
std::cout << hough_acc.size() << " " << hough_acc[0].size() << std::endl;
for (size_t i = 0; i < hough_acc.size(); i++) {
for (size_t j = 0; j < hough_acc[0].size(); j++) {
img_mat.at<int> (i,j) = hough_acc[i][j];
}
}
imwrite("../output/ps1-2-b-1.png", img_mat);
}
theta varies from -90 to 89. I am getting negative rho values. Right now I am just replacing the negative who with a positive one but am not getting a correct answer. What do I do to the negative rho? Please explain the answer.
theta = arctan (y / x)
rho = x * cos(theta) + y * sin(theta)
Edited code :
bool hough_lines_acc(cv::Mat img_a_edges, std::vector<std::vector<int> > &hough_acc,\
std::vector<double> thetas, std::vector<double> rhos, int rho_resolution, int theta_resolution) {
int img_w = img_a_edges.cols;
int img_h = img_a_edges.rows;
int max_votes = 0;
int min_votes = INT_MAX;
for (size_t r = 0; r < img_h; r++) {
for (size_t c = 0; c < img_w; c++) {
if(img_a_edges.at<int>(r, c) == 255) {
for (size_t i = 0; i < thetas.size(); i++) {
thetas[i] = (thetas[i] * M_PI / 180);
double rho = ( (c * cos(thetas[i])) + (r * sin(thetas[i])) );
int buff = ++hough_acc[static_cast<int>(abs(rho))][static_cast<int>(i)];
if (buff > max_votes) {
max_votes = buff;
}
if (buff < min_votes) {
min_votes = buff;
}
}
}
}
}
double div = static_cast<double>(max_votes) / 255;
int threshold = 10;
int possible_edge = round(static_cast<double>(max_votes) / div) - threshold;
props({
{"max votes", max_votes},
{"min votes", min_votes},
{"scale", div}
});
// needed for scaling intensity for contrast
// not sure if I am doing it correctly
for (size_t r = 0; r < hough_acc.size(); r++) {
for (size_t c = 0; c < hough_acc[0].size(); c++) {
double val = hough_acc[r][c] / div;
if (val < 0) {
val = 0;
}
hough_acc[r][c] = static_cast<int>(val);
}
}
cv::Mat img_mat = cv::Mat(hough_acc.size(), hough_acc[0].size(), CV_8UC1, cv::Scalar(0));
for (size_t i = 0; i < hough_acc.size(); i++) {
for (size_t j = 0; j < hough_acc[0].size(); j++) {
img_mat.at<uint8_t> (i,j) = static_cast<uint8_t>(hough_acc[i][j]);
}
}
imwrite("../output/ps1-2-b-1.png", img_mat);
return true;
}
Still not correct output. What is the error here?
atan2 of two positive numbers... should not be giving you negative angles, it should only be giving you a range of 0-90
also for the hough transform, I think you want everything relative to one point (ie 0,0 in this case). I think for that you would actually want to make theta=90-atan2(r,c)
Admittedly though, I am a bit confused as I thought you had to encode line direction, rather than just "edge pt". ie I thought at each edge point you had to provide a discrete array of guessed line trajectories and calculate rho and theta for each one and throw all of those into your accumulator. As is... I am not sure what you are calculating.
The following code is for finding the closest point pairs problem in Introduction to Programming with C++ liang textbook. and I'm trying to edit it so it can find all closest point pairs if multiple closest pairs exist.
#include <iostream>
#include <cmath>
using namespace std;
/** Compute the distance between two points (x1, y1) and (x2, y2) */
double getDistance(double x1, double y1, double x2, double y2)
{
return sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1));
}
int main()
{
const int NUMBER_OF_POINTS = 8;
// Each row in points represents a point
double points[NUMBER_OF_POINTS][2];
cout << "Enter " << NUMBER_OF_POINTS << " points: ";
for (int i = 0; i < NUMBER_OF_POINTS; i++)
cin >> points[i][0] >> points[i][1];
// p1 and p2 are the indices in the points array
int p1 = 0, p2 = 1; // Initial two points
double shortestDistance = getDistance(points[p1][0], points[p1][1],
points[p2][0], points[p2][1]); // Initialize
// Compute distance for every two points
for (int i = 0; i < NUMBER_OF_POINTS; i++)
{
for (int j = i + 1; j < NUMBER_OF_POINTS; j++)
{
double distance = getDistance(points[i][0], points[i][1],
points[j][0], points[j][1]); // Find distance
if (shortestDistance > distance)
{
p1 = i; // Update p1
p2 = j; // Update p2
shortestDistance = distance; // Update shortestDistance
}
}
}
// Display result
cout << "The closest two points are " <<
"(" << points[p1][0] << ", " << points[p1][1] << ") and (" <<
points[p2][0] << ", " << points[p2][1] << ")";
return 0;
}
I solved it by using a new array, distance-points , and save the distance with the points pair whenever the distance is calculated, after that I loop over the new array and print out the shortest distance, but I think there is smarter solution for sure, Im quite new in programming :)
double distance_points[28][5];
int f = 0 ;
// Compute distance for every two points
for (int i = 0; i < NUMBER_OF_POINTS; i++)
{
for (int j = i + 1; j < NUMBER_OF_POINTS; j++)
{
double distance = getDistance(points[i][0], points[i][1],
points[j][0], points[j][1]); // Find distance
distance_points[f][0] = distance;
distance_points[f][1] = points[i][0];
distance_points[f][2] = points[i][1];
distance_points[f][3] = points[j][0];
distance_points[f][4] = points[j][1];
f++;
}
}
You may change your algorithm to stock results in vector:
std::vector<int> p1, p2;
double shortestDistance = getDistance(points[p1][0], points[p1][1],
points[p2][0], points[p2][1]); // Initialize
for (int i = 0; i < NUMBER_OF_POINTS; i++) {
for (int j = i + 1; j < NUMBER_OF_POINTS; j++) {
const double distance = getDistance(points[i][0], points[i][1],
points[j][0], points[j][1]);
if (shortestDistance >= distance) {
if (shortestDistance > distance) {
p1.clear();
p2.clear();
shortestDistance = distance; // Update shortestDistance
}
p1.push_back(i); // Update p1
p2.push_back(j); // Update p2
}
}
}
This question already has answers here:
How do I use arrays in C++?
(5 answers)
Why aren't variable-length arrays part of the C++ standard?
(10 answers)
Closed 8 years ago.
I was implementing a version of the closest pair problem using the algorithmic technique of divide and conquer. However, when I try and compile my code, in several spots I get the error "Expected constant expression". I am aware that arrays are supposed to have constant values in them, but I'm not quite sure what's wrong in this case. I tried to research solutions and many people suggested using malloc, but it seems to be generally frowned upon. Would someone be able to help me fix this? Below is the code with the errors commented hopefully well enough that you can see them. Thank you so much in advance for your help, I really appreciate it!
#include <iostream>
#include <float.h>
#include <stdlib.h>
#include <math.h>
using namespace std;
//A struct to represent the points on an x,y plane
struct Point{
int x, y;
};
//function to sort x coordinates
int compareX(const void* a, const void* b){
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->x - p2->x);
}
//function to sort y coordinates
int compareY(const void* a, const void* b){
Point *p1 = (Point *)a, *p2 = (Point *)b;
return (p1->y - p2->y);
}
//function to find the distance between any two points
float dist(Point p1, Point p2){
return sqrt( (float)(p1.x - p2.x) * (p1.x - p2.x) +
(float)(p1.y - p2.y) * (p1.y - p2.y)
);
}
//utility function to find the minimum of any two float values
float min(float x, float y){
if(x < y)
return x;
else
return y;
}
//brute force function to find the closest of two points
float bruteforce(Point P[], int n){
float min = FLT_MAX;
for(int i=0; i<n; i++){
for(int j = i+1; j < n; j++)
if(dist(P[i], P[j]) < min)
min = dist(P[i], P[j]);
}
return min;
}
//function to find the distance between the closest points of a given size
float closestArray(Point array1[], int size, float d){
float min = d; //initialize the minimum distance as d
//go through the points 1 by 1 and try the next until the difference is smaller than d
for (int i=0; i < size; i++)
for (int j= i + 1; j< size && (array1[i].y - array1[i].y) < min; j++)
if(dist(array1[i],array1[j]) < min)
min = dist(array1[i], array1[j]);
return min;
}
float closestPoint(Point Px[], Point Py[], int n){
if(n <= 3)
return bruteforce(Px, n);
//find the middle point
int mid = n/2;
Point midPoint = Px[mid];
//divide the points along the vertical line
Point Pyleft[mid + 1]; //left of vertical line <--- ERROR
Point Pyright[n-mid-1]; //right of vertical line <--- ERROR
int li = 0; //index of left subarray
int ri = 0; //index of right subarray
for ( int i =0; i<n; i++){
if (Py[i].x <= midPoint.x)
Pyleft[li++] = Py[i];
else
Pyright[ri++] = Py[i];
}
//calculate the smallest ditance dl on the left middle point and dr on the right side
float dl = closestPoint(Px, Pyleft, mid);
float dr = closestPoint(Px + mid, Pyright, n-mid);
//find the smaller of the two distances
float d = min(dl, dr);
//build another array Q that contains points closer than d to the line passing through the middle
Point q[n]; // <--- ERROR
int j = 0;
for (int i = 0; i<n; i++)
if(abs(Py[i].x - midPoint.x) < d)
q[j] = Py[i], j++;
return min(d, closestArray(q, j, d) );
}
//function that finds the smallerst distance
float closest(Point P[], int n){
Point Px[n]; //<--- ERROR
Point Py[n]; //<---ERROR
for(int i=0; i < n; i++)
{
Px[i] = P[i];
Py[i] = P[i];
}
qsort(Px, n, sizeof(Point), compareX);
qsort(Py, n, sizeof(Point), compareY);
//recursive function to find smallest distance
return closestPoint(Px, Py, n);
}
int main()
{
Point P[] = {{2, 3}, {12, 30}, {40, 50}, {5, 1}, {12, 10}, {3, 4}};
int n = sizeof(P) / sizeof(P[0]);
cout << "The smallest distance is " << closest(P, n);
return 0;
}