//
//  subpixel_edge.h
//  subpixel_edge
//
//  Created by Mehdi Stapleton on 2015-06-17.
//
//

#ifndef __SUBPIXEL_EDGE__
#define __SUBPIXEL_EDGE__

//#define XCODE_COMPILATION
#ifndef XCODE_COMPILATION
#include "mex.h"
#endif

#include <sstream>
#include <string>
#include <cstdio>
#include <iostream>
#include <fstream>

#include <vector>
#include <cmath>

//---------------------------------------------------------------
//             GENERAL PREPROCESSOR DEFINITIONS
//---------------------------------------------------------------

//#define SHOW_DEBUG_INFO
#define BITS_PER_BYTE 8
#define BUILD_LOG_BUFFER_SIZE 10000
#define PI 3.141592653589793238462643383

//---------------------------------------------------------------
//                      TYPE DEFINITIONS
//---------------------------------------------------------------

typedef double   matrix_t;
typedef float    grad_t;
typedef float    subpixel_t;
typedef uint32_t index_t;

//---------------------------------------------------------------
//                      GLOBAL CONSTANTS
//---------------------------------------------------------------

#ifdef XCODE_COMPILATION
static const std::string PROJECT_DIR_PATH = "../subpixel_edge_c/";
#else
static const std::string PROJECT_DIR_PATH = "/Users/mehdistapleton/Documents/MATLAB/MASC/Image Processing Tools/Edge Detection/subpixel_edge_c/";
#endif


//---------------------------------------------------------------
//                      LOGGING FUNCTIONS
//---------------------------------------------------------------

#define LOG_DEBUG(txt) {std::ostringstream debug_oss; \
debug_oss <<"Debug:"<< txt << ";\n"; \
mexPrintf(debug_oss.str().c_str());}

#define LOG_PRINT(txt) {std::ostringstream debug_oss; \
debug_oss << txt << ";\n"; \
mexPrintf(debug_oss.str().c_str());}

#define LOG_WARNING(txt) {std::ostringstream debug_oss; \
debug_oss <<"Warning:"<< txt << ";\n"; \
mexPrintf(debug_oss.str().c_str());}

#define LOG_ERROR(txt) {std::ostringstream debug_oss; \
debug_oss <<"Error:"<< txt << ";\n"; \
mexPrintf(debug_oss.str().c_str());}

//---------------------------------------------------------------
//                      MACROS
//---------------------------------------------------------------

#define PROJECT_RELPATH(relpath) PROJECT_DIR_PATH + relpath

#define IS_REAL_3D_FULL_DOUBLE(P) (!mxIsComplex(P) && \
        mxGetNumberOfDimensions(P) == 3 && !mxIsSparse(P) && mxIsDouble(P))

#define IS_REAL_2D_FULL_DOUBLE(P) (!mxIsComplex(P) && \
        mxGetNumberOfDimensions(P) == 2 && !mxIsSparse(P) && mxIsDouble(P))

#define IS_REAL_SCALAR(P) (IS_REAL_2D_FULL_DOUBLE(P) && mxGetNumberOfElements(P) == 1)

//-------------------------------------------------------------------------
//                     HELPER EDGE DETECTION FUNCTIONS
//-------------------------------------------------------------------------

void select_nbors (const matrix_t angle, int const* nbor1, int const* nbor2, int const* nbor3, matrix_t &locStep, matrix_t const* locPos);

void get_gradient(const matrix_t* xGradImgIn, const matrix_t* yGradImgIn, int rOffset, int cOffset, int r, int c, matrix_t* const grad, int nRows, int nCols);

matrix_t compute_interpolated_directional_derivative(const matrix_t* normGrad, const matrix_t* nbor1Grad, const matrix_t* nbor2Grad, const matrix_t* nbor3Grad, matrix_t locStep);

double atan2pi(double y, double x);

double tanpi(double ang);

//---------------------------------------------------------------
//                 MAIN FUNCTION DECLARATIONS
//---------------------------------------------------------------

/*\brief perform Devernay-NMS-subpixel-accurate method
 */
void subpixel_edge_c(matrix_t* xGradImgIn, matrix_t* yGradImgIn, matrix_t* edgeImgOut, matrix_t* xDeltaImgOut, matrix_t* yDeltaImgOut, int nRows, int nCols);


#endif /* __SUBPIXEL_EDGE__ */

