You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

635 lines
14 KiB
C

1 month ago
#pragma once
#include "DrawOperator/Xy.h"
#include "DrawOperator/one.h"
#include "Util.h"
class CTextFaciesBuilder {
public:
CTextFaciesBuilder& FontLocation(double x, double y)
{
m_x = x;
m_y = y;
return *this;
}
CTextFaciesBuilder& FontSize(double width, double height)
{
m_width = width;
m_height = height;
return *this;
}
CTextFaciesBuilder& Text(const CString& text)
{
m_text = text;
return *this;
}
std::unique_ptr<CText> Build() const
{
std::unique_ptr<CText> pText = std::make_unique<CText>();
const CString formatStr = "%lf,%lf,0.00000000 98\n"
"{\n"
"%s\n"
"}\n"
"%lf %lf 0.000000 0 400 0 0 0 1 0 16 0 0 Times New Roman";
CString content;
content.Format(formatStr, m_x, m_y, m_text, m_width, m_height);
CMemFile memFile((BYTE*)content.GetString(), content.GetLength());
pText->Read(memFile, CUR_VERSION);
return pText;
}
private:
double m_x = 0.0;
double m_y = 0.0;
double m_width = 21.0;
double m_height = 52.0;
CString m_text;
};
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD> Item
*/
class FaciesLegendItem
{
public:
FaciesLegendItem(CXy& xy, const CString& name, COLORREF color)
: m_sourceXy(xy), m_name(name), m_color(color)
{
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>ռ<EFBFBD>÷<EFBFBD>Χ
*
* \param x <EFBFBD><EFBFBD><EFBFBD>½<EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param y <EFBFBD><EFBFBD><EFBFBD>½<EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param width <EFBFBD><EFBFBD>
* \param height <EFBFBD><EFBFBD>
*/
void SetBounds(double x, double y, double width, double height)
{
m_x = x;
m_y = y;
m_width = width;
m_height = height;
}
/**
* <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>ռ<EFBFBD>÷<EFBFBD>Χ
*
* \param x <EFBFBD><EFBFBD><EFBFBD>½<EFBFBD> x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param y <EFBFBD><EFBFBD><EFBFBD>½<EFBFBD> y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param width <EFBFBD><EFBFBD>
* \param height <EFBFBD><EFBFBD>
*/
void GetBounds(double& x, double& y, double& width, double& height) const
{
x = m_x;
y = m_y;
width = m_width;
height = m_height;
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
*
* \param targetXy Ҫ<EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD> xy
*/
void Build(CXy& targetXy) const
{
BuildCurveRange(targetXy);
BuildElement(targetXy);
BuildName(targetXy);
}
private:
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param targetXy Ҫ<EFBFBD><EFBFBD><EFBFBD>ɵ<EFBFBD>Ŀ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
*/
void BuildName(CXy& targetXy) const
{
CString name = m_name;
auto [x, y] = MeasureNameLocation(name);
std::unique_ptr<CText> pText = CTextFaciesBuilder()
.FontLocation(x, y)
.FontSize(10, 26)
.Text(name)
.Build();
CLayer* pLayer = targetXy.FindAddLayer(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>"));
std::unique_ptr<COne> pOne = std::make_unique<COne>();
pOne->SetLayer(pLayer);
pOne->SetValueSafe(pText.release());
pOne->SetColor(RGB(0, 0, 0));
targetXy.AddTailOne(pOne.release());
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param targetXy
*/
void BuildElement(CXy& targetXy) const
{
// <20><><EFBFBD>ɲ<EFBFBD>ɫ<EFBFBD><C9AB><EFBFBD><EFBFBD>
std::unique_ptr<CCurveEx> pCurve = std::make_unique<CCurveEx>();
pCurve->Create(5);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double y = m_y + m_height * (1 - m_canvasHeightRatio);
// <20><>С<EFBFBD><D0A1>Χ
double left = m_x + 5.0;
double right = m_x + m_width - 5.0;
double bottom = y + 5.0;
double top = m_y + m_height - 5.0;
// <20><><EFBFBD>ƾ<EFBFBD><C6BE><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С<EFBFBD><D0A1><EFBFBD>ķ<EFBFBD>Χ<EFBFBD><CEA7>
pCurve->x[0] = left;
pCurve->y[0] = bottom;
pCurve->x[1] = right;
pCurve->y[1] = bottom;
pCurve->x[2] = right;
pCurve->y[2] = top;
pCurve->x[3] = left;
pCurve->y[3] = top;
pCurve->x[4] = left;
pCurve->y[4] = bottom;
pCurve->GetLocation();
std::unique_ptr<COne> pOne = std::make_unique<COne>();
pOne->SetValueSafe(pCurve.release());
//<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pOne->HowToViewCurve = new CHowToViewCurve;
pOne->HowToViewCurve->EnableDrawSourceCurve(true);
CCurvePropertiesEx* pr = new CCurvePropertiesEx;
pr->color = m_color;
pr->m_nFlags = PLINE_SOLID;
pOne->HowToViewCurve->Add(pr);
CLayer* pLayer = targetXy.FindAddLayer(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>"));
pOne->SetLayer(pLayer);
pOne->SetColor(m_color); // ʹ<><CAB9> FaciesLegendItem <20>д洢<D0B4><E6B4A2><EFBFBD><EFBFBD>ɫ
targetXy.AddTailOne(pOne.release());
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param point
* \param range
*/
void CenterPointInRange(CPointNameEx& point, const CRect8& range) const
{
point.x0 = range.left + (range.right - range.left) / 2;
point.y0 = range.bottom + (range.top - range.bottom) / 2;
point.SetName(""); // <20><><EFBFBD>յ<EFBFBD><D5B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߷ŵ<EFBFBD>Ŀ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param curve
* \param range
*/
void CenterCurveInRange(CCurveEx& curve, const CRect8& range) const
{
CRect8 oldRange;
oldRange.SetRect(1e100, -1e100, -1e100, 1e100);
curve.GetRange(oldRange);
CRect8 newRange = ScaleRect(range, 0.9);
for (int i = 0; i < curve.num; i++)
{
auto [x, y] = ScalePoint(curve.x[i], curve.y[i], oldRange, newRange);
curve.x[i] = x;
curve.y[i] = y;
}
curve.GetLocation();
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD>
*
* \param targetXy
*/
void BuildCurveRange(CXy& targetXy) const
{
std::unique_ptr<CCurveEx> pCurve = std::make_unique<CCurveEx>();
pCurve->Create(5);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double y = m_y + m_height * (1 - m_canvasHeightRatio);
pCurve->x[0] = m_x;
pCurve->y[0] = y;
pCurve->x[1] = m_x + m_width;
pCurve->y[1] = y;
pCurve->x[2] = m_x + m_width;
pCurve->y[2] = m_y + m_height;
pCurve->x[3] = m_x;
pCurve->y[3] = m_y + m_height;
pCurve->x[4] = m_x;
pCurve->y[4] = y;
pCurve->GetLocation();
CLayer* pLayer = targetXy.FindAddLayer(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>"));
std::unique_ptr<COne> pOne = std::make_unique<COne>();
pOne->SetValueSafe(pCurve.release());
pOne->SetLayer(pLayer);
pOne->SetColor(RGB(0, 0, 0));
targetXy.AddTailOne(pOne.release());
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>η<EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD>ŵ<EFBFBD><EFBFBD><EFBFBD>һ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>η<EFBFBD>Χ
*
* \param x x <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param y y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param oldRange <EFBFBD>ɵķ<EFBFBD>Χ
* \param newRange <EFBFBD>µķ<EFBFBD>Χ
* \return <EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD><EFBFBD><EFBFBD> x y <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*/
std::pair<double, double> ScalePoint(double x, double y, const CRect8& oldRange, const CRect8& newRange) const
{
double xMin = oldRange.left;
double xMax = oldRange.right;
double yMin = oldRange.bottom;
double yMax = oldRange.top;
double newXMin = newRange.left;
double newXMax = newRange.right;
double newYMin = newRange.bottom;
double newYMax = newRange.top;
double newX = ((x - xMin) / (xMax - xMin)) * (newXMax - newXMin) + newXMin;
double newY = ((y - yMin) / (yMax - yMin)) * (newYMax - newYMin) + newYMin;
return { newX, newY };
}
/**
* <EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \return
*/
CRect8 CanvasRect() const
{
return CRect8(m_x, m_y + m_height, m_x + m_width, m_y + m_height * (1 - m_canvasHeightRatio));
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param rect Ҫ<EFBFBD><EFBFBD><EFBFBD>ŵľ<EFBFBD><EFBFBD><EFBFBD>
* \param scaleFactor <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><EFBFBD>
* \return
*/
CRect8 ScaleRect(const CRect8& rect, double scaleFactor) const
{
assert(scaleFactor > 0);
double width = rect.right - rect.left;
double height = rect.top - rect.bottom;
double newWidth = width * scaleFactor;
double newHeight = height * scaleFactor;
double left = rect.left + (width - newWidth) / 2;
double top = rect.top - (height - newHeight) / 2;
double right = rect.right - (width - newWidth) / 2;
double bottom = rect.bottom + (height - newHeight) / 2;
return CRect8(left, top, right, bottom);
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƹ<EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD> x, y λ<EFBFBD><EFBFBD>
*
* \param text
* \return
*/
std::pair<double, double> MeasureNameLocation(const CString& name) const
{
double x = m_x + m_width / 2; // Ҫ<><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵĿ<D6B5><C4BF>ȼ<EFBFBD><C8BC><EFBFBD> x <20><>λ<EFBFBD>ã<EFBFBD>Ŀǰ<C4BF><C7B0> x <20><><EFBFBD>õ<EFBFBD><C3B5>м<EFBFBD>λ<EFBFBD>ã<EFBFBD>ò<EFBFBD><C3B2><EFBFBD>ı<EFBFBD><C4B1><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD>м<EFBFBD>
double height = m_height * (1 - m_canvasHeightRatio); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>
double y = m_y + height; // y ̧<><CCA7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾ<EFBFBD><CABE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߴ<EFBFBD>
y -= height * m_nameOffsetRatio; // <20><><EFBFBD>ƶ<EFBFBD><C6B6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾλ<CABE><CEBB>
return { x, y };
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><C7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵѿ<C7B5><D1BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x y <20><><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD>λ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵһ<D2B5><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double m_x = 0.0; // <20><><EFBFBD><EFBFBD> x
double m_y = 0.0; // <20><><EFBFBD><EFBFBD> y
double m_width = 2.0; // <20><><EFBFBD><EFBFBD>
double m_height = 1.0; // <20>߶<EFBFBD>
double m_nameOffsetRatio = 7.0 / 52.0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʾλ<CABE>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ƹ߶<C6B8>ռ<EFBFBD><D5BC>
double m_canvasHeightRatio = 65.0 / 117.0; // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶Ⱥ<DFB6><C8BA><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶ȵı<C8B5><C4B1><EFBFBD>
CXy& m_sourceXy; // ԭͼ<D4AD><CDBC>xy<78><79><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>ɷ<EFBFBD><C9B7>ŵ<EFBFBD>ͼ<EFBFBD><CDBC> xy
CString m_name; // ͼ<><CDBC>item<65><6D><EFBFBD><EFBFBD>
COLORREF m_color; // ͼ<><CDBC>item<65><6D>ɫ
};
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
*
*/
class FaciesLegend
{
public:
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> + <20><>ɫ<EFBFBD>б<EFBFBD>
FaciesLegend(CXy& xy, double x, double y, const CString& title, const std::vector<std::pair<CString, COLORREF>>& items, double width = 600, int columns = 3)
: m_sourceXy(xy), m_x(x), m_y(y), m_width(width), m_columns(columns)
{
for (const auto& item : items)
{
m_boxes.emplace_back(m_sourceXy, item.first, item.second);
}
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
*
* \return <EFBFBD><EFBFBD><EFBFBD>ع<EFBFBD><EFBFBD><EFBFBD><EFBFBD>õ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>ָ<EFBFBD><EFBFBD>
*/
std::unique_ptr<CInsertBlock> Build()
{
ComputeLayout();
std::unique_ptr<CXy> pNewXy = std::make_unique<CXy>();
pNewXy->color = 0;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>߿<EFBFBD>
BuildCurveRange(*pNewXy);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
BuildTitle(*pNewXy);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC> item
for (auto& box : m_boxes)
{
box.Build(*pNewXy);
}
// <20><><EFBFBD><EFBFBD> Block
std::unique_ptr<CInsertBlock> pBlock = std::make_unique<CInsertBlock>();
pBlock->SetXy(pNewXy.release());
return pBlock;
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>ÿ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>ռ<EFBFBD>Ŀռ<EFBFBD>
*
*/
void ComputeLayout()
{
size_t rows = m_boxes.size() / m_columns + (m_boxes.size() % m_columns == 0 ? 0 : 1);
size_t columns = m_columns;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>м<EFBFBD>϶<EFBFBD><CFB6><EFBFBD><EFBFBD>
double horizontalSpacing = CalcHorizontalSpacing(m_width, static_cast<int>(columns), m_boxWidthSpacingRatio);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>Ŀ<EFBFBD><C4BF><EFBFBD>
m_boxWidth = horizontalSpacing * m_boxWidthSpacingRatio;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>ĸ߶ȣ<DFB6><C8A3><EFBFBD><EFBFBD>ƿ<EFBFBD><C6BF>߱<EFBFBD>Ϊ 10 <20><> 8
m_boxHeight = m_boxWidth * m_widthHeightRatio;
m_titleHeight = m_boxWidth * m_titleWidthRatio;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD>߶<EFBFBD>
m_height = m_boxHeight * rows + m_titleHeight;
for (size_t i = 0; i < m_boxes.size(); i++)
{
size_t row = i / columns;
size_t column = i % columns;
// x ƫ<><C6AB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǰ<EFBFBD><C7B0><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><D0BF><EFBFBD><EFBFBD>м<EFBFBD>϶<EFBFBD><CFB6><EFBFBD><EFBFBD>
double xOffset = column * m_boxWidth + (column + 1) * horizontalSpacing;
double yOffset = (row + 1) * m_boxHeight;
// y <20><><EFBFBD><EFBFBD>Ķ<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ߵ<EFBFBD>λ<EFBFBD><CEBB>
// Ȼ<><C8BB><EFBFBD><EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>
// <20><><EFBFBD><EFBFBD><EFBFBD>¼<EFBFBD>ȥ<EFBFBD><C8A5><EFBFBD><EFBFBD><EFBFBD><EFBFBD>λ<EFBFBD><CEBB>
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD><EFBFBD><EFBFBD> y <20>Ƿ<EFBFBD><C7B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD>½ǵ<C2BD>λ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD>Ի<EFBFBD>Ҫ<EFBFBD>ټ<EFBFBD><D9BC><EFBFBD> boxHeight
yOffset = m_height - yOffset - m_titleHeight;
m_boxes[i].SetBounds(xOffset, yOffset, m_boxWidth, m_boxHeight);
}
OffsetBoxes();
}
double GetWidth() const
{
return m_width;
}
double GetHeight() const
{
return m_height;
}
private:
/**
* ǰ<EFBFBD><EFBFBD><EFBFBD>ļ<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǻ<EFBFBD><EFBFBD><EFBFBD> 0,0 Ϊ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><EFBFBD><EFBFBD><EFBFBD> m_x, m_y <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ƫ<EFBFBD><EFBFBD>
*
*/
void OffsetBoxes()
{
for (auto& box : m_boxes)
{
double x = 0.0;
double y = 0.0;
double width = 0.0;
double height = 0.0;
box.GetBounds(x, y, width, height);
box.SetBounds(m_x + x, m_y + y, width, height);
}
}
// <20><><EFBFBD>ѿ<EFBFBD><D1BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD>ľ<EFBFBD><C4BE><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>С
std::tuple<double, double, double, double> ScaleRect(double x, double y, double width, double height, double scaleFactor)
{
assert(scaleFactor > 0 && scaleFactor <= 1);
double newWidth = width * scaleFactor;
double newHeight = width * scaleFactor;
double newX = x + ((width - newWidth) / 2);
double newY = y + ((height - newHeight) / 2);
return { newX, newY, newWidth, newHeight };
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param targetXy Ҫ<EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>Ŀ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
*/
void BuildCurveRange(CXy& targetXy) const
{
std::unique_ptr<CCurveEx> pCurve = std::make_unique<CCurveEx>();
pCurve->Create(5);
pCurve->x[0] = m_x;
pCurve->y[0] = m_y;
pCurve->x[1] = m_x + m_width;
pCurve->y[1] = m_y;
pCurve->x[2] = m_x + m_width;
pCurve->y[2] = m_y + m_height;
pCurve->x[3] = m_x;
pCurve->y[3] = m_y + m_height;
pCurve->x[4] = m_x;
pCurve->y[4] = m_y;
pCurve->GetLocation();
CLayer* pLayer = targetXy.FindAddLayer(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>"));
std::unique_ptr<COne> pOne = std::make_unique<COne>();
pOne->SetValueSafe(pCurve.release());
pOne->SetLayer(pLayer);
pOne->HowToViewCurve = CreateBorderHowToView().release();
targetXy.AddTailOne(pOne.release());
}
/**
* <EFBFBD><EFBFBD><EFBFBD>ɡ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD>С<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param targetXy Ҫ<EFBFBD><EFBFBD><EFBFBD>Ƶ<EFBFBD>Ŀ<EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>
*/
void BuildTitle(CXy& targetXy) const
{
double x = m_x + m_width * 0.5;
double y = m_y + m_height - m_titleHeight * m_titleOffsetRatio;
std::unique_ptr<CText> pText = CTextFaciesBuilder()
.FontLocation(x, y)
.FontSize(21, 52)
.Text("<EFBFBD><EFBFBD> <20><>")
.Build();
CLayer* pLayer = targetXy.FindAddLayer(_T("<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD>"));
std::unique_ptr<COne> pOne = std::make_unique<COne>();
pOne->SetLayer(pLayer);
pOne->SetValueSafe(pText.release());
pOne->SetColor(RGB(0, 0, 0));
targetXy.AddTailOne(pOne.release());
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Χ<EFBFBD>߿<EFBFBD><EFBFBD>ߵ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \return
*/
std::unique_ptr<CHowToViewCurve> CreateBorderHowToView() const
{
std::unique_ptr<CCurvePropertiesEx> prop1 = std::make_unique<CCurvePropertiesEx>();
prop1->m_size = 0;
prop1->color = abs(16777215);
prop1->m_nFlags = 65568;
prop1->m_SmoothStep = 0;
prop1->m_offset = 0;
prop1->m_stuCurveWave.T = 0;
prop1->m_stuCurveWave.T = 0;
prop1->m_stuCurveWave.A = 0;
prop1->m_stuCurveWave.dnum = 0;
std::unique_ptr<CCurvePropertiesEx> prop2 = std::make_unique<CCurvePropertiesEx>();
prop2->m_size = 0;
prop2->color = abs(0);
prop2->m_nFlags = 65536;
prop2->m_SmoothStep = 0;
prop2->m_offset = 0;
prop2->m_stuCurveWave.T = 0;
prop2->m_stuCurveWave.T = 0;
prop2->m_stuCurveWave.A = 0;
prop2->m_stuCurveWave.dnum = 0;
std::unique_ptr<CHowToViewCurve> pHowToViewCurve = std::make_unique<CHowToViewCurve>();
pHowToViewCurve->Add(prop1.release());
pHowToViewCurve->Add(prop2.release());
return pHowToViewCurve;
}
/**
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD>ܿ<EFBFBD><EFBFBD>ȣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>п<EFBFBD><EFBFBD>ͼ<EFBFBD>϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>϶<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
*
* \param width <EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param n <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* \param ratio <EFBFBD>кͼ<EFBFBD>϶<EFBFBD>Ŀ<EFBFBD><EFBFBD>ȱ<EFBFBD><EFBFBD><EFBFBD>
* \return
*/
double CalcHorizontalSpacing(double width, int n, double ratio) const
{
// <20>ܹ<EFBFBD> n <20>У<EFBFBD><D0A3><EFBFBD>϶Ϊ n + 1 <20><>
// (n + 1) * space + n * boxWidth = width
// boxWidth = ratio * space
// (n + 1) * space + n * (ratio * space) = width
// (n + 1 + n * ratio) * space = width
// space = width / (n + 1 + n * ratio)
return width / (n + 1 + n * ratio);
}
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ǵ<EFBFBD><C7B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ǵѿ<C7B5><D1BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> x y <20><><EFBFBD><EFBFBD><EFBFBD>½<EFBFBD>λ<EFBFBD>ã<EFBFBD><C3A3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ҵһ<D2B5><D2BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
double m_x = 0.0;
double m_y = 0.0;
double m_width = 512.0;
double m_height = 421.0;
CString m_title;
// ÿ<>м<EFBFBD><D0BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC> Item <20><><EFBFBD><EFBFBD>Ϊ 46 <20><> 106
double m_boxWidthSpacingRatio = 106.0 / 46.0;
// ͼ<>п<EFBFBD><D0BF>߱<EFBFBD>
double m_widthHeightRatio = 106.0 / 117.0;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD><DFB6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ<EFBFBD><CDBC><EFBFBD><EFBFBD><EFBFBD>ȵı<C8B5><C4B1><EFBFBD>
double m_titleWidthRatio = 77.0 / 106.0;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʼλ<CABC><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>߶<EFBFBD>ռ<EFBFBD><D5BC>
double m_titleOffsetRatio = 10.0 / 77.0;
double m_boxWidth = 0.0;
double m_boxHeight = 0.0;
double m_titleHeight = 0.0;
int m_columns = 3;
std::vector<CString> m_layers;
std::vector<FaciesLegendItem> m_boxes;
CXy& m_sourceXy;
};