Implementing a hermite curve - c++

I am using this website on how to compute a hermite curve under the heading The Math in Matrix Form to make a hermite curve.
Here is my code so far...
// calculate hermite curve
GLfloat S[4][1];
GLfloat C[4][3] = {{height, 0, 0},
{0, radius, 0},
{0, 2 * radius, 0},
{-2 * height, 0, 0}};
GLfloat h[4][4] = {{ 2,-2, 1, 1},
{-3, 3,-2,-1},
{ 0, 0, 1, 0},
{ 1, 0, 0, 0}};
unsigned int rows;
unsigned int cols;
float val;
for (int x = 0; x < l_vertices; x++) {
float segment = (float)x / l_vertices;
S[0][0] = pow(segment, 3);
S[1][0] = pow(segment, 2);
S[2][0] = pow(segment, 1);
S[3][0] = 1;
GLfloat midwayArray[4][4] = {{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0},
{ 0, 0, 0, 0}};
GLfloat finalArray[4][1] = { 0, 0, 0, 0};
rows = 4;
cols = 4;
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
for (unsigned int k = 0; k < 1; k++) {
val = S[i][k] * h[k][j];
midwayArray[i][j] += val;
}
}
}
rows = 4;
cols = 1;
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
for (unsigned int k = 0; k < 4; k++) {
val = midwayArray[i][k] * C[k][j];
finalArray[i][j] += val;
}
}
}
profileCurve[0][x] = finalArray[0][0];
profileCurve[1][x] = finalArray[1][0];
profileCurve[2][x] = finalArray[2][0];
}
But I am getting mainly zeros for some reason. I think my matrix multiplication is not being done correctly.
Also, just some information on how my code currently works. The first inner nested for loop is multiplying S and h just like the website says. Then the second inner nested for loop is multiplying the result of the previous matrix multiplication with C just like the website says.
I think assign the result coordinates of the final array for that iteration of x to my profileCurve array which is going to store all the coordinates that make up the hermite curve.

Related

My c++ code returns 3 (after throwing an instance of bad_alloc)

My code returns 3 even though everything seems to be right. It previously returned 255, and i re-arranged it a bit, and now it returns 3. It also says "terminate called after throwing an instance of 'std::bad_alloc'".
I looked it up on Google but I can't find any solution. Any idea why this happens?
#include <iostream>
#include <vector>
using namespace std;
std::vector<int> calculeazaPunctul(double pct[]) {
double pctfinal[2];
double xv = pct[0];
double yv = pct[1];
double zv = pct[2];
double res = .02;
double xk = 1;
double yk = 1;
double zk = -2;
cout << "h" << endl;
double zp = 0;
double xp = xv - ((xv - xk) * (zv - zp));
xp = xp / (((zv - zk != 0) ? (zv - zk) : 0.0001));
double yp = yv - ((yv - yk) * (zv - zp));
yp = yp / (((zv - zk != 0) ? (zv - zk) : 0.0001));
return {(int)((res * 2 * (xp * 50 + 100))), (int)((res * (yp * 50 + 100)))};
}
int main()
{
double puncte[8][3] = {{1, 0, -1},
{1, 0, 1},
{-1, 0, 1},
{-1, 0, -1},
{1, 1, -1},
{1, 1, 1},
{-1, 1, 1},
{-1, 1, -1}};
std::vector<std::vector<int> > pcteFinal;
pcteFinal.resize(8);
for (int i = 0; i < 8; i++) {
pcteFinal[i] = calculeazaPunctul(puncte[i]);
}
std::vector<std::vector<char> > image;
image.resize(10);
for (int y = 0; y < 10; y++) {
std::vector<char> row;
image[y] = row;
for (int x = 0; x < 20; x++) {
image[y].push_back('.');
}
}
for (int i = 0; i < 8; i++) {
if (pcteFinal[i][0] < 20 && pcteFinal[i][0] >= 0)
{
if (pcteFinal[i][1] < 10 && pcteFinal[i][0] >= 0)
{
image[pcteFinal[i][0]][pcteFinal[i][1]] = '#';
}
}
}
for (int y = 0; y < 10; y++) {
for (int x = 0; x < 20; x++) {
cout << image[y][x];
}
cout << endl;
}
return 0;
}

Distance transform :

Kindly help me with the working of Distance transform and rectify the errors. I have tried Borgefors' method which has defined values for Eucledian measure. I get all zeros as output.
Below is the code which i have tried.
int _tmain(int argc, _TCHAR* argv[])
{
Mat v = imread("ref.png", 0);
imshow("input", v);
Mat forward = (Mat_<uchar>(5, 5) << 0, 11, 0, 11, 0, 11, 7, 5, 7, 11, 0, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
Mat backward = (Mat_<uchar>(5, 5) << 0,0,0,0,0, 0,0,0,0,0, 0, 0, 0, 5, 0, 11, 7, 5, 7, 11, 0, 11, 0, 11, 0);
Mat op = cv::Mat::zeros(v.size(), CV_32FC1);
cout << forward;
cout << backward;
int r = v.rows;
int c = v.cols;
float min=100, x = 0;
int size = 3;
int lim = size / 2;
int a, b;
for (int i = lim; i <= r-1-lim; i++)
{
for (int j = lim; j <= c-1-lim; j++)
{
for (int k = -lim; k <= lim; k++)
{
for (int l = -lim; l <= lim; l++)
{
a = (v.at<uchar>(i + k, j + l));
b=(forward.at<uchar>(k + lim, l + lim));
x = a + b;
if (x>0 && min> x)
min = x;
}
}
op.at<float>(i, j) = min;
}
}
cout << min;
for (int i = (r-1-lim); i >lim; i--)
{
for (int j = (c-1-lim); j >lim; j--)
{
for (int k = -lim; k <= lim; k++)
{
for (int l = -lim; l <= lim; l++)
{
a = (v.at<uchar>(i + k, j + l));
b = (forward.at<uchar>(k + lim, l + lim));
x = a + b;
if (x >0 && min> x) min = x;
}
}
op.at<float>(i, j) = min;
}
}
cout << op;
Mat res = cv::Mat::ones(v.size(), CV_8UC1);
normalize(op, res, 0, 255, NORM_MINMAX);
imshow("output",res);
waitKey(0);
return 0;
}
Which is the best method and why it is the best way to implement Distance Transform?
Here is how to fix your code:
Apply the backward mask in the backward loop, you apply the same mask there as in the forward loop.
Use only the defined weights, the values in the mask where you wrote 0 are not part of the mask. Those pixels don't have a distance of 0!
As for your second question, it's probably out of scope for SO. But what the best method is depends very much on the goal. You have a fast and relatively accurate method here, there are other methods that are exact but more expensive.

I have a c++ code for sobel operator on pgm image, my code compiles but fails to give me the required results

So here is the function that does the sobel process:
void sobelOperator(int& x, int& y)
{
ImageType image;
for(int i = 0; i<x; i++)
{
for(int j = 0; j<y; j++)
{
//constants
const int MATRIX_MAX = 3;
const int PIXEL_MAX = 255;
//value for the new cell calculation
int GXpixel = 0, GYpixel = 0, Gpixel = 0;
//Sobel Horizontal Mask or matrix for the Kx convolution
const int sobelKxFilterMatrix[3][3] = {{1, 0, -1}, {2, 0, -2}, {1, 0, -1}};
//Sobel Vertical Mask or matrix for the Ky convolution
const int sobelKyFilterMatrix[3][3] = {{1, 2, 1}, {0, 0, 0}, {-1, -2, -1}};
//for addressing into filter array and into picture
int iFilter, jFilter;
int iPic, jPic;
//Loop to iterate over picture and filter window to perform sobel operation
for(iFilter = 0, iPic =- 1; iFilter < MATRIX_MAX && iPic >= 1; iFilter++, iPic++)
{
for(jFilter = 0, jPic =-1; jFilter < MATRIX_MAX && jPic >= 1; jFilter++, jPic++)
{
int val;
image.getPixelVal(x+iPic, y+jPic, val);
GXpixel += (val * sobelKxFilterMatrix[iFilter][jFilter]);
GYpixel += (val * sobelKyFilterMatrix[iFilter][jFilter]);
}
}
//check for pixel saturation
if(GXpixel > PIXEL_MAX){GXpixel = PIXEL_MAX;}
if(GYpixel > PIXEL_MAX){GYpixel = PIXEL_MAX;}
//normalize pixel
Gpixel = static_cast<int>(sqrt(pow(static_cast<double>(GXpixel), 2.0) + pow(static_cast<double>(GYpixel), 2.0)));
image.setPixelVal(i, j, Gpixel);
}
}
}
I have a c++ code for sobel operator on pgm image, my code compiles but fails to give me the required results. Can anyone tell me what is wrong?
This part
for(iFilter = 0, iPic =- 1; iFilter < MATRIX_MAX && iPic >= 1; iFilter++, iPic++)
looks wrong.
You assign -1 to iPic and then test if iPic >= 1. That will always be false.

How do you find out in which sub-grid a 2D array element is located

C++ beginner here. I'm currently trying to make a sudoku solving program, so I have to check whether a value exists in the 9x9 box it's located in.
This is my code for checking if the element follows the rules:
//constants for rows and columns of the sudoku puzzle, can be changed
const int ROWS = 9;
const int COLS = 9;
bool follows_rule(int grid[ROWS][COLS], int rowIndex, int colIndex, int value){
for (int i = 0; i < COLS; i++){
if (grid[rowIndex][i] == value) //check if there are any other values on the same column
return false;
if (grid[i][colIndex] == value) //or the same row
return false;
}
//to-do: check if another equal value exists in the 9x9 box
return true;
}
//returns true if another element has the same value as "value", false otherwise
bool exists_in_2d_array(int grid[ROWS][COLS], int value){
for (int x = 0; x < ROWS / 3; x++)
{
for (int y = 0; y < COLS / 3; y++)
{
if (grid[x][y] == value)
{
return true;
}
}
}
return false;
}
My idea was to find out which 9x9 box the coordinates of the current element lead to, then put that 9x9 grid in another 2D array and check if the element's value exists somewhere else in the grid. I don't really know how, though.
The SUDOKU rules require that the digit is used only once:
Rule 1: in each row
Rule 2: in each column
Rule 3: in each 3x3 subgrid of the 9x9 grid
Function follows_rule() checks for a given grid position, if the value would be allowed or not. For the moment it checks only rules 1 and 2. I propose you the following code for rule 3:
bool follows_rule(int grid[ROWS][COLS], int rowIndex, int colIndex, int value){
for (int i = 0; i < COLS; i++){
if (grid[rowIndex][i] == value)
return false;
if (grid[i][colIndex] == value) // ATTENTION THIS IS OK BECAUSE ROWS==COLS !!
return false;
}
// Check if another equal value exists in the 3x3 box
int sgc = (colIndex / 3) * 3; // in wich subgrid are we ?
int sgr = (rowIndex / 3) * 3;
// check all the elements of the 3x3 grid startic at sgr, sgc
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (grid[sgr + i][sgc + j] == value)
return false;
return true;
}
You can test the 3x3 verification with the following code:
int sudoku[ROWS][COLS] = {
{ 1, 0, 0, 0, 0, 0, 0, 8, 0 },
{ 0, 0, 2, 0, 0, 0, 0, 0, 0 },
{ 0, 3, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 3, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 5, 0, 0, 0 },
{ 0, 0, 0, 0, 8, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
if (follows_rule(sudoku, 1, 0, 1) == false
&& follows_rule(sudoku, 1, 0, 4) == true
&& follows_rule(sudoku, 5, 5, 8) == false
&& follows_rule(sudoku, 5, 5, 1) == false
&& follows_rule(sudoku, 5, 5, 7) == true)
cout << "Test ok !" << endl;
else cout << "Tests failed" << endl;
Accepted answer does not calculate the subgrids correctly , sgc and and sgr needs to be multiplied with 3 too after division to crrectly identify the subgrid vertices
public boolean isValidEntry(char[][] board, int row , int col,char val)
{
for(int i = 0 ; i < 9 ;i++){
if(board[row][i] == val)
return false;
}
for(int j = 0 ; j < 9 ;j++){
if(board[j][col] == val)
return false;
}
int sgc = col / 3; // in wich subgrid are we ?
int sgr = row / 3;
// check all the elements of the 3x3 grid startic at sgr, sgc
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++)
if (board[(3*sgr) + i][(3*sgc) + j] == val)
return false;
}
return true;
}

Find largest area in 2d array in c++

I need to write recursive function in c++ that finds largest area of number '1' in 2d array that contains only 1 or 0.
Example:
int Arr[5][8] =
{
{ 0, 0, 0, 0, 1, 1, 0, 0, },
{ 1, 0, 0, 1, 1, 1, 0, 0, },
{ 1, 1, 0, 1, 0, 1, 1, 0, },
{ 0, 0, 0, 1, 1, 1, 1, 0, },
{ 0, 1, 1, 0, 0, 0, 0, 0, },
};
Visual example: http://s23.postimg.org/yabwp6h23/find_largest.png
Largest area of this array is 12, second largest is 3 and third largest is 2.
I was thinking to do this with something similar to flood fill algorithm, but just can't figure out how.
bool visited[5][8];
int i,j;
// variables for the area:
int current_area = 0, max_area = 0;
int Arr[5][8]={ // type your map of values here
}
// functions
void prepare_visited_map() {
for(i=0;i<5;i++) {
for(j=0;j<8;j++) visited[i][j] = false;
}
}
// recursive function to calculate the area around (x,y)
void calculate_largest_area(int x, int y) {
if(visited[x][y]) return;
// check if out of boundaries
if(x<0 || y<0 || x>=5 || y>=8) return;
// check if the cell is 0
if(!Arr[x][y]) {
visited[x][y] = true;
return;
}
// found a propper cell, proceed
current_area++;
visited[x][y] = true;
// call recursive function for the adjacent cells (north, east, south, west)
calculate_largest_area(x,y-1);
calculate_largest_area(x+1,y);
calculate_largest_area(x,y+1);
calculate_largest_area(x-1,y);
// by the end of the recursion current_area will hold the area around the initial cell
}
// main procedure where the above functions are used
int mian() {
// calculate the sorrounding area of each cell, and pick up the largest of all results
for(i=0;i<5;i++) {
for(j=0;j<8;j++) {
prepare_visited_map();
calculate_largest_area(i,j);
if(current_area > max_area) max_area = current_area;
}
}
printf("Max area is %d",max_area");
}
Hope this was helpful :)
I was thinking to do this with something similar to flood fill algorithm
I think that's a pretty good way to do it. Apply flood fill to any 1, counting the ones and replacing them with zeros.
Repeat until the grid consists entirely of zeroes.
The following will print out the sizes of the connected components in no particular order:
#include <iostream>
constexpr int N = 5;
constexpr int M = 8;
int arr[N][M] =
{
{ 0, 0, 0, 0, 1, 1, 0, 0, },
{ 1, 0, 0, 1, 1, 1, 0, 0, },
{ 1, 1, 0, 1, 0, 1, 1, 0, },
{ 0, 0, 0, 1, 1, 1, 1, 0, },
{ 0, 1, 1, 0, 0, 0, 0, 0, },
};
int fill(int arr[N][M], int r, int c) {
int count = 0;
if (r < N && arr[r][c]) {
for (int i = c; i >= 0 && arr[r][i]; --i) {
arr[r][i] = 0;
count += fill(arr, r + 1, i) + 1;
}
for (int i = c + 1; i < M && arr[r][i]; ++i) {
arr[r][i] = 0;
count += fill(arr, r + 1, i) + 1;
}
}
return count;
}
int print_components(int arr[N][M]) {
for (int r = 0; r < N; ++r) {
for (int c = 0; c < M; ++c) {
if (arr[r][c]) {
std::cout << fill(arr, r, c) << std::endl;
}
}
}
}
int main() {
print_components(arr);
}
something like,
int max_area = 0;
foreach y
foreach x
if (pos[y][x] == 1 && !visited[y][x])
{
int area = 0;
Queue queue = new Queue();
queue.push(new Point(x, y));
visited[y][x] = true;
while (!queue.empty())
{
Point pt = queue.pop();
area++;
foreach neightboor of pt (pt.x±1, pt.y±1)
if (pos[neightboor.y][neightboor.x] == 1 && !visited[neightboor.y][neightboor.x])
{
visited[neightboor.y][neightboor.x] = true;
queue.push(new Point(neightboor.x, neightboor.y));
}
}
if (area > max_area)
max_area = area;
}
Quick approach, but I don't know if there is a way to do this in a sane way (recursive
call for each element does not scale for C++ because call stack is limited)
int maxy = 5
int maxx = 8
int areasize(int x, int y) {
if (x < 0 || y < 0 || x > maxx || y > maxy || !Arr[y][x])
return 0;
Arr[y][x] = 0;
return 1
+ areasize(x + 1, y)
+ areasize(x - 1, y)
+ areasize(x, y + 1)
+ areasize(x, y - 1);
}
maxarea = 0;
for (int y = 0; y < maxy; y++) {
for (int x = 0; x < maxx; x++) {
maxarea = std::max(maxarea, areasize(x, y));
}
}