2016-03-19 06:57:51 +13:00
|
|
|
|
|
|
|
|
|
|
|
// PatternPosition.cpp: implementation of the CPatternPosition class.
|
|
|
|
//
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
2017-05-09 00:13:29 +12:00
|
|
|
#ifdef _MSC_VER
|
2016-03-19 06:57:51 +13:00
|
|
|
#pragma warning(disable : 4996)
|
|
|
|
#endif
|
|
|
|
|
2016-04-15 19:44:40 +12:00
|
|
|
#include <memory>
|
|
|
|
|
2016-03-19 06:57:51 +13:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "PatternPosition.h"
|
|
|
|
#include "SError.h"
|
|
|
|
#include "SDef.h"
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// Construction/Destruction
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
CPatternPosition::~CPatternPosition() { m_pos.clear(); }
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool CPatternPosition::isInSet(const int nbSet, const int *set, const int val) {
|
|
|
|
for (int i = 0; i < nbSet; i++)
|
|
|
|
if (set[i] == val) return true;
|
|
|
|
return false;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
2016-07-14 00:05:06 +12:00
|
|
|
static int pp_intCompare(const void *a, const void *b) {
|
2016-06-15 18:43:10 +12:00
|
|
|
int *aa = (int *)a;
|
|
|
|
int *bb = (int *)b;
|
2016-03-19 06:57:51 +13:00
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
if (*aa < *bb) return -1;
|
|
|
|
if (*aa > *bb) return 1;
|
|
|
|
return 0;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPatternPosition::makeRandomPositions(const int nbPat, const int nbPixel,
|
2016-06-15 18:43:10 +12:00
|
|
|
const int lX, const int lY,
|
|
|
|
const UCHAR *sel) {
|
|
|
|
try {
|
|
|
|
const UCHAR *pSel = sel;
|
|
|
|
int threshold = RAND_MAX * (double)nbPat / (double)nbPixel;
|
|
|
|
for (int y = 0; y < lY; y++)
|
|
|
|
for (int x = 0; x < lX; x++, pSel++)
|
|
|
|
if (*pSel > (UCHAR)0) {
|
|
|
|
if (rand() < threshold) {
|
|
|
|
SPOINT xyp = {x, y};
|
|
|
|
m_pos.push_back(xyp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} catch (exception) {
|
|
|
|
char s[50];
|
2020-04-12 17:19:20 +12:00
|
|
|
snprintf(s, sizeof(s), "in Pattern Position Generation");
|
2016-06-15 18:43:10 +12:00
|
|
|
throw SMemAllocError(s);
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void CPatternPosition::getPosAroundThis(const int lX, const int lY,
|
|
|
|
const UCHAR *lSel, const int xx,
|
|
|
|
const int yy, int &xPos, int &yPos) {
|
|
|
|
vector<SPOINT> ddc;
|
|
|
|
prepareCircle(ddc, 2.0);
|
|
|
|
|
|
|
|
int qx = 0, qy = 0, q = 0;
|
|
|
|
for (vector<SPOINT>::iterator p = ddc.begin(); p != ddc.end(); p++) {
|
|
|
|
int x = xx + p->x;
|
|
|
|
int y = yy + p->y;
|
|
|
|
if (x >= 0 && y >= 0 && x < lX && y < lY)
|
|
|
|
if (*(lSel + y * lX + x) > (UCHAR)0) {
|
|
|
|
qx += x;
|
|
|
|
qy += y;
|
|
|
|
q++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (q > 0) {
|
|
|
|
double dx = (double)qx / (double)q;
|
|
|
|
double dy = (double)qy / (double)q;
|
|
|
|
xPos = I_ROUND(dx);
|
|
|
|
yPos = I_ROUND(dy);
|
|
|
|
} else {
|
|
|
|
xPos = xx;
|
|
|
|
yPos = yy;
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
bool CPatternPosition::findEmptyPos(const int lX, const int lY,
|
|
|
|
const UCHAR *lSel, int &xPos, int &yPos,
|
|
|
|
SRECT &bb) {
|
|
|
|
int y = 0;
|
|
|
|
for (y = 0; y <= yPos; y++)
|
|
|
|
for (int x = xPos; x <= bb.x1; x++)
|
|
|
|
if (*(lSel + y * lX + x) == (UCHAR)1) {
|
|
|
|
// getPosAroundThis(lX,lY,lSel,x,y,xPos,yPos);
|
|
|
|
xPos = x;
|
|
|
|
yPos = y;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (y = yPos; y <= bb.y1; y++)
|
|
|
|
for (int x = bb.x0; x <= bb.x1; x++)
|
|
|
|
if (*(lSel + y * lX + x) == (UCHAR)1) {
|
|
|
|
// getPosAroundThis(lX,lY,lSel,x,y,xPos,yPos);
|
|
|
|
xPos = x;
|
|
|
|
yPos = y;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPatternPosition::eraseCurrentArea(const int lX, const int lY, UCHAR *lSel,
|
2016-06-15 18:43:10 +12:00
|
|
|
vector<SPOINT> &ddc, const int xx,
|
|
|
|
const int yy) {
|
|
|
|
for (vector<SPOINT>::iterator pDdc = ddc.begin(); pDdc != ddc.end(); pDdc++) {
|
|
|
|
int x = xx + pDdc->x;
|
|
|
|
int y = yy + pDdc->y;
|
|
|
|
if (x >= 0 && y >= 0 && x < lX && y < lY) {
|
|
|
|
UCHAR *pSel = lSel + y * lX + x;
|
|
|
|
if (*(pSel) == (UCHAR)1) *(pSel) = (UCHAR)2;
|
|
|
|
}
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void CPatternPosition::sel0255To01(const int lX, const int lY, UCHAR *sel,
|
|
|
|
SRECT &bb) {
|
|
|
|
UCHAR *pSel = sel;
|
|
|
|
bb.x0 = lX;
|
|
|
|
bb.y0 = lY;
|
|
|
|
bb.x1 = -1;
|
|
|
|
bb.y1 = -1;
|
|
|
|
for (int y = 0; y < lY; y++)
|
|
|
|
for (int x = 0; x < lX; x++, pSel++)
|
|
|
|
if (*pSel >= (UCHAR)1) {
|
|
|
|
*pSel = (UCHAR)1;
|
|
|
|
bb.x0 = std::min(x, bb.x0);
|
|
|
|
bb.x1 = std::max(x, bb.x1);
|
|
|
|
bb.y0 = std::min(y, bb.y0);
|
|
|
|
bb.y1 = std::max(y, bb.y1);
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
2016-06-15 18:43:10 +12:00
|
|
|
void CPatternPosition::prepareCircle(vector<SPOINT> &v, const double r) {
|
|
|
|
try {
|
|
|
|
double r2 = r * r;
|
|
|
|
int rr = (int)r + 1;
|
|
|
|
for (int y = -rr; y <= rr; y++)
|
|
|
|
for (int x = -rr; x <= rr; x++)
|
|
|
|
if ((double)(x * x + y * y) <= r2) {
|
|
|
|
SPOINT sp = {x, y};
|
|
|
|
v.push_back(sp);
|
|
|
|
}
|
|
|
|
} catch (exception) {
|
|
|
|
char s[50];
|
2020-04-12 17:19:20 +12:00
|
|
|
snprintf(s, sizeof(s), "Position Generation");
|
2016-06-15 18:43:10 +12:00
|
|
|
throw SMemAllocError(s);
|
|
|
|
}
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|
|
|
|
|
|
|
|
void CPatternPosition::makeDDPositions(const int lX, const int lY, UCHAR *sel,
|
2016-06-15 18:43:10 +12:00
|
|
|
const double minD, const double maxD) {
|
|
|
|
const int maxNbDDC = 20;
|
|
|
|
vector<SPOINT> ddc[maxNbDDC];
|
|
|
|
|
|
|
|
// Checking parameters
|
|
|
|
if (lX <= 0 || lY <= 0 || !sel) return;
|
|
|
|
if (minD > maxD) return;
|
|
|
|
// Preparing circles
|
|
|
|
int nbDDC = fabs(maxD - minD) < 0.001 ? 1 : maxNbDDC;
|
|
|
|
try {
|
|
|
|
if (nbDDC == 1) {
|
|
|
|
prepareCircle(ddc[0], minD);
|
|
|
|
} else {
|
|
|
|
double dDist = (maxD - minD) / (double)(nbDDC - 1);
|
|
|
|
double dist = minD;
|
|
|
|
for (int i = 0; i < nbDDC; i++, dist += dDist)
|
|
|
|
prepareCircle(ddc[i], dist);
|
|
|
|
}
|
|
|
|
} catch (SMemAllocError) {
|
|
|
|
throw;
|
|
|
|
}
|
|
|
|
// Preparing local selection
|
|
|
|
std::unique_ptr<UCHAR[]> lSel(new UCHAR[lX * lY]);
|
|
|
|
if (!lSel) {
|
|
|
|
char s[50];
|
2020-04-12 17:19:20 +12:00
|
|
|
snprintf(s, sizeof(s), "in Pattern Position Generation");
|
2016-06-15 18:43:10 +12:00
|
|
|
throw SMemAllocError(s);
|
|
|
|
}
|
|
|
|
memcpy(lSel.get(), sel, lX * lY * sizeof(UCHAR));
|
|
|
|
|
|
|
|
SRECT bb;
|
|
|
|
sel0255To01(lX, lY, lSel.get(), bb);
|
|
|
|
if (bb.x0 > bb.x1 || bb.y0 > bb.y1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
int x = 0, y = 0;
|
|
|
|
while (findEmptyPos(lX, lY, lSel.get(), x, y, bb)) {
|
|
|
|
SPOINT sp = {x, y};
|
|
|
|
m_pos.push_back(sp);
|
|
|
|
int iddc = nbDDC == 1 ? 0 : rand() % nbDDC;
|
|
|
|
eraseCurrentArea(lX, lY, lSel.get(), ddc[iddc], sp.x, sp.y);
|
|
|
|
}
|
|
|
|
} catch (exception) {
|
|
|
|
char s[50];
|
2020-04-12 17:19:20 +12:00
|
|
|
snprintf(s, sizeof(s), "in Pattern Position Generation");
|
2016-06-15 18:43:10 +12:00
|
|
|
throw SMemAllocError(s);
|
|
|
|
}
|
|
|
|
// memcpy(sel,lSel,lX*lY);
|
2016-03-19 06:57:51 +13:00
|
|
|
}
|