📄 v2.cpp
字号:
m_corner.m_y = (x1 * m_90.m_pos * m_90.m_pos -
x2 * m_main.m_pos * m_main.m_pos) / denom + m_y_rf;
}
else if (FL_ABS(m_main.m_pos) < EPSILON)
{ // main feature is at origin
m_corner.m_x = m_90.m_x;
m_corner.m_y = m_90.m_y;
}
// else perpendicular feature is at origin.
// But we defaulted to using (m_main.m_x, m_main.m_y), which works.
}
/*------------------------------------------------------------------------*/
// write text feature information to a file.
void CFeature::write
( ofstream& outFile,
bool names, // If names is true, give a text name,
// otherwise write numbers for feature_type;
int verbosity // 0 for brief, 1 for longer ...
)
{
if (m_corner.m_type == eNO_FEATURE || m_corner.m_type == eNOT_AVAILABE)
{
outFile << endl;
return;
}
// set to show 1 decimal place
int oldPrecision = outFile.precision(1);
outFile.setf( ios::fixed, ios::floatfield );
outFile << m_x_rf << '\t' << m_y_rf << '\t' << m_diam_rf << '\t'
<< m_lateral << '\t';
// int type_index = (int) m_corner.m_type;
// outFile << featureName[ type_index] << '\t';
m_corner.write( outFile, names, verbosity );
m_main.write( outFile, names, verbosity );
if (verbosity > 0)
{
// Write perpendicular features
m_90.write( outFile, names, verbosity );
/* // Write +45 degree features
m_45.write( outFile, names, verbosity );
// Write -45 degree features
m_135.write( outFile, names, verbosity ); */
}
outFile << endl;
outFile.precision(oldPrecision); // restore previous precision
}
/*------------------------------------------------------------------------*/
// Compute distance from feature to base position
float CFeature::PositionDifference
( Data_1D& base, // the answer; true position of feature
bool fromRfCenter // if true, use center of receptive field.
// if false, use location of found feature
)
{
double distance = 0.0;
if (m_corner.m_type == eNO_FEATURE || m_corner.m_type == eNOT_AVAILABE)
return (float) distance;
// intersection of base line with perpendicular thru m_main.m_x,y
double x = base.m_x;
double y = base.m_y;
double degrees = base.m_degrees;
double xFrom = m_main.m_x;
double yFrom = m_main.m_y;
if (fromRfCenter)
{
xFrom = m_x_rf;
yFrom = m_y_rf;
}
switch (base.m_type)
{
case eNO_FEATURE:
case eNOT_AVAILABE:
// distance is meaningless
break;
case eEDGE:
case eWHITE_LINE:
case eBLACK_LINE:
// TO DO: case of mismatched edges and bars
while (degrees > 180)
degrees -= 180;
while (degrees < 0)
degrees += 180;
if (degrees > 90 - EPSILON && degrees < 90 + EPSILON)
x = xFrom;
else if (degrees > 180 - EPSILON || degrees < EPSILON)
y = yFrom;
else
{
double slope = tan( degrees * PI / 180.0);
x = (slope / (slope * slope + 1.0)) * ( yFrom - base.m_y +
xFrom / slope + base.m_x * slope);
y = slope * (x - base.m_x) + base.m_y;
}
distance = sqrt( (x - xFrom) * (x - xFrom) + (y - yFrom) * (y - yFrom));
if (xFrom - x + yFrom - y < 0)
distance = -distance;
// if matched an edge to a bar, report the distance to the edge of the bar
if (m_main.m_type == eEDGE &&
(base.m_type == eBLACK_LINE || base.m_type == eWHITE_LINE))
{
double half_width = base.m_width * 0.5;
distance += fabs( distance - half_width) < fabs( distance + half_width)?
-half_width : half_width;
}
if (base.m_type == eEDGE &&
(m_main.m_type == eBLACK_LINE || m_main.m_type == eWHITE_LINE))
{
double cosine =
fabs( cos( (base.m_degrees - m_main.m_degrees) * PI / 180.0));
if (cosine > EPSILON)
{
double half_width = base.m_width * 0.5 / cosine;
distance += fabs( distance - half_width) <
fabs( distance + half_width)?
-half_width : half_width;
}
}
break;
case eCORNER:
case eDARK_CORNER:
case eLIGHT_CORNER:
case eBLOB:
case eDARK_BLOB:
case eLIGHT_BLOB:
default:
distance = sqrt( (x - xFrom) * (x - xFrom) + (y - yFrom) * (y - yFrom));
if (xFrom - x + yFrom - y < 0)
distance = -distance;
break;
}
return (float) distance;
}
/*------------------------------------------------------------------------*/
// Compute error in type identification
// Returned: difference in type values.
int CFeature::TypeDifference( Data_1D& base )
{
enum feature_type answer = base.m_type;
float half_width = base.m_width * 0.5;
bool edge1seen = base.DoesIntersect(m_x_rf, m_y_rf, m_diam_rf/2, half_width);
bool edge2seen = edge1seen;
if (answer == eBLACK_LINE || answer == eWHITE_LINE)
edge2seen = base.DoesIntersect(m_x_rf, m_y_rf, m_diam_rf/2, -half_width);
// if the feature is not in the small receptive field, no feature.
if (!edge1seen && !edge2seen)
answer = eNO_FEATURE;
// if the feature is a bar, can we see both edges?
if ((answer == eBLACK_LINE || answer == eWHITE_LINE) &&
(!edge1seen || !edge2seen))
answer = eEDGE; // can't see far bar edge
return (int) (m_corner.m_type - answer);
}
/*------------------------------------------------------------------------*/
void CFeature::FindPlotInfo( Outline& shape, bool useMain )
{ // replaces CadData
Data_1D& oneD = useMain? m_main : m_90;
float radius = m_diam_rf / 2; /* effective radius of smaller filter */
if (oneD.m_type == eNO_FEATURE || oneD.m_type == eNOT_AVAILABE)
return;
shape.color = EDGE_COLOR;
float half_width = oneD.m_width * 0.5;
float p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y;
bool edge1seen = oneD.FindIntersect(m_x_rf, m_y_rf, radius, half_width,
&p1x, &p1y, &p2x, &p2y);
bool edge2seen = edge1seen;
if (oneD.m_type == eBLACK_LINE || oneD.m_type == eWHITE_LINE)
{
edge2seen = oneD.FindIntersect(m_x_rf, m_y_rf, radius, -half_width,
&p4x, &p4y, &p3x, &p3y);
shape.color = oneD.m_type == eWHITE_LINE?
LIGHT_BAR_COLOR: DARK_BAR_COLOR;
}
if (Is2D())
{
shape.color = CORNER_COLOR;
if (oneD.m_type == eEDGE)
{
p2x = m_corner.m_x;
p2y = m_corner.m_y;
}
}
if (!edge1seen && !edge2seen)
return; // should not happen
// Make a quadrilateral describing the bar or line
POINT vertex;
vertex.x = Round(p1x);
vertex.y = Round(p1y);
shape.segment.Add( vertex );
POINT firstPoint = vertex;
vertex.x = Round(p2x);
vertex.y = Round(p2y);
shape.segment.Add( vertex );
if (oneD.m_type != eEDGE)
{
vertex.x = Round(p3x);
vertex.y = Round(p3y);
shape.segment.Add( vertex );
vertex.x = Round(p4x);
vertex.y = Round(p4y);
shape.segment.Add( vertex );
shape.segment.Add( firstPoint );
}
shape.thickness = 1;
}
/*------------------------------------------------------------------------*/
void CFeature::CadData( Outline& shape, bool useMain )
{
/* cad_info: write information that is useful for making a drawing of
the features that were located. */
/* This routine added 5/11/95 by Tyler C. Folsom */
// float m_x_rf, m_y_rf, /* center point of the filter */
// float m_pos, /* position of feature relative to center */
// float m_angle, /* angle of feature in radians */
// int m_type, /* feature type */
// float m_bar_width, /* width of a bar */
if (!useMain)
return; // corner drawing is not yet working
Data_1D& oneD = useMain? m_main : m_90;
float radius = m_diam_rf / 2; /* effective radius of smaller filter */
float sin_a, cos_a, half_bar;
/* intersection of circle with line from center to feature location. */
float cx, cy;
/* end points of the feature in the smaller filter */
float px, py, qx, qy;
/* centerline of bar */
float pcx, pcy, qcx, qcy;
/* angle by which (cx, cy) is rotated into (px, py), (qx, qy). */
double alpha;
POINT vertex;
float sin_th = oneD.m_sin_th;
float cos_th = oneD.m_cos_th;
/* The graphics origin is at the upper left.
X axis points right and Y axis points down.
0 degrees points down and a positive angle is clockwise.
Thus for rotation, the origin is at (0,R) and the angle is positive.
x = -radius * sin_th;
y = radius * cos_th;
(cx, cy) is normal to (x,y)
*/
/* intersection of circle with line from center to feature location. */
if (oneD.m_degrees < 180)
{
cx = radius * cos_th;
cy = radius * sin_th;
}
else
{
cx = -radius * cos_th;
cy = -radius * sin_th;
}
if (oneD.m_type == eBLACK_LINE || oneD.m_type == eWHITE_LINE)
{
half_bar = (float) 0.5 * oneD.m_width;
shape.color = oneD.m_type == eWHITE_LINE?
LIGHT_BAR_COLOR: DARK_BAR_COLOR;
if (FL_ABS(oneD.m_pos) < half_bar)
{ /* center line is the longest segment */
cos_a = oneD.m_pos / radius;
sin_a = (float) sqrt(1.0 - cos_a * cos_a);
/* centerline of bar: (cx, cy) rotated +/- alpha */
pcx = m_x_rf + cx * cos_a + cy * sin_a;
pcy = m_y_rf - cx * sin_a + cy * cos_a;
qcx = m_x_rf + cx * cos_a - cy * sin_a;
qcy = m_y_rf + cx * sin_a + cy * cos_a;
/* inner edge of bar */
px = pcx - half_bar * cos_th;
py = pcy - half_bar * sin_th;
qx = qcx - half_bar * cos_th;
qy = qcy - half_bar * sin_th;
}
else
{ /* inner edge is the longest segment */
alpha = acos ((double) ((oneD.m_pos - half_bar) / radius));
sin_a = (float) sin(alpha);
cos_a = (float) cos(alpha);
/* inner edge of bar */
px = m_x_rf + cx * cos_a + cy * sin_a;
py = m_y_rf - cx * sin_a + cy * cos_a;
qx = m_x_rf + cx * cos_a - cy * sin_a;
qy = m_y_rf + cx * sin_a + cy * cos_a;
/* centerline of bar */
pcx = px + half_bar * cos_th;
pcy = py + half_bar * sin_th;
qcx = qx + half_bar * cos_th;
qcy = qy + half_bar * sin_th;
}
// Make a quadrilateral describing the bar
vertex.x = Round(px);
vertex.y = Round(py);
POINT firstPoint = vertex;
shape.segment.Add( vertex );
vertex.x = Round(qx);
vertex.y = Round(qy);
shape.segment.Add( vertex );
/* outer edge of bar */
px = pcx + half_bar * cos_th;
py = pcy + half_bar * sin_th;
qx = qcx + half_bar * cos_th;
qy = qcy + half_bar * sin_th;
vertex.x = Round(qx);
vertex.y = Round(qy);
shape.segment.Add( vertex );
vertex.x = Round(px);
vertex.y = Round(py);
shape.segment.Add( vertex );
shape.segment.Add( firstPoint );
}
else /* a step edge */
{ /* compute the points where the edge meets the boundary of the smaller
receptive field */
shape.color = EDGE_COLOR;
alpha = acos ((double) (oneD.m_pos / radius));
sin_a = (float) sin(alpha);
cos_a = (float) cos(alpha);
// Points on the edge are (cx, cy) rotated by +/- alpha.
px = m_x_rf + cx * cos_a + cy * sin_a;
py = m_y_rf - cx * sin_a + cy * cos_a;
qx = m_x_rf + cx * cos_a - cy * sin_a;
qy = m_y_rf + cx * sin_a + cy * cos_a;
vertex.x = Round(px);
vertex.y = Round(py);
shape.segment.Add( vertex );
vertex.x = Round(qx);
vertex.y = Round(qy);
shape.segment.Add( vertex );
}
/*
if (Is2D())
{
shape.color = CORNER_COLOR;
}
*/
if (oneD.m_strength < 0.5)
{
shape.thickness = 1;
}
else if (oneD.m_strength < 1.0)
{
shape.thickness = 2;
}
else if (oneD.m_strength < 1.5)
{
shape.thickness = 3;
}
else
{
shape.thickness = 4;
}
}
/*------------------------------------------------------------------------*/
// draw a circle corresponding to the small filter.
BOOL CFeature::DrawCircle(HDC hDeviceContext)
{
return
(
Arc( hDeviceContext,
m_x_rf - m_diam_rf/2, // x Up Left
m_y_rf - m_diam_rf/2, // y Up Left
m_x_rf + m_diam_rf/2, // x Low Right
m_y_rf + m_diam_rf/2, // y Low Right
m_x_rf, // x start
m_y_rf + m_diam_rf/2, // y start
m_x_rf, // x end
m_y_rf + m_diam_rf/2 // y end
)
);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -