FMHN#67510 ARC ondersteuning savepoint

svn path=/Slnkdwf/trunk/; revision=52147
This commit is contained in:
Jos Groot Lipman
2021-06-30 07:09:31 +00:00
parent 5bac3a5f80
commit e00e2b3b5e
3 changed files with 215 additions and 14 deletions

View File

@@ -69,6 +69,8 @@ interface IWhipFile : IDispatch{
[propget, id(27), helpstring("property vectorDpi")] HRESULT vectorDpi([out, retval] LONG* pVal);
[propget, id(28), helpstring("property DwgLimits")] HRESULT DwgLimits([out, retval] IBoundingBox** pVal);
[id(29), helpstring("method SymbolOrigin")] HRESULT SymbolOrigin([in] BSTR symbolName, [in] DOUBLE dwgX, [in] DOUBLE dwgY);
[propget, id(30), helpstring("property minMergeDistance")] HRESULT minMergeDistance([out, retval] DOUBLE* pVal);
[propput, id(30), helpstring("property minMergeDistance")] HRESULT minMergeDistance([in] DOUBLE newVal);
};
[
object,

View File

@@ -83,9 +83,11 @@ CWhipFile::CWhipFile()
m_reLayers.Parse(".*", FALSE);
m_hintScale = -1.0;
m_minContSize = 0.20e6; // Minimale opp om herkend te worden.
m_minMergeDistance = - 1.0; // Minimale mm afstand om lijnsegmenten te mergen, default uit
m_forFind = TRUE; // backward compatible
m_activeLayerName = "";
m_vdpi = 0;
m_builder_len = 0;
// Predefine fixed symbols
// Merk op dat m_contunits hier nog gewoon de default identity matrix is
@@ -274,6 +276,7 @@ void CWhipFile::read_for_contours()
m_W2DFile.set_text_action(my_process_text);
m_W2DFile.set_polyline_action(my_process_polyline);
m_W2DFile.set_outline_ellipse_action(my_process_outlineEllipse);
// Shiften tijdens *inlezen* om overflow te voorkomen
// Problemen: hoe achterhaal je op een nette manier zo vroeg hoeveel je moet shiften
@@ -306,6 +309,7 @@ void CWhipFile::read_for_contours()
// We gaan er later nog een keer door voor de plattegrond. Geen processing dan
m_W2DFile.set_text_action(WT_Text::default_process);
m_W2DFile.set_outline_ellipse_action(WT_Outline_Ellipse::default_process);
m_W2DFile.set_polyline_action(WT_Polyline::default_process);
}
@@ -335,7 +339,7 @@ void CWhipFile::processLabels()
for (size_t lbl=0; lbl<m_SLNKLabels.GetCount(); lbl++)
{
WT_Text text = m_SLNKLabels[lbl];
bool found = false;
// Find inside which Polygon it falls
// When multiple: choose smallest!
CSLNKContourImpl *prevContour = NULL;
@@ -365,6 +369,7 @@ void CWhipFile::processLabels()
}
else
prevContour = contour;
found = true;
prevContour->m_Key = text.string().ascii();
// Spaties voor of achteraan geven op de lange termijn
// problemen als we via XML communiceren
@@ -399,6 +404,9 @@ void CWhipFile::processLabels()
}
}
}
if (!found)
myTRACE("\nLabel %s has no matching contour", text.string().ascii());
}
return;
}
@@ -440,6 +448,134 @@ WT_Result CWhipFile::my_process_layer (WT_Layer & layer, WT_File & file)
return WT_Result::Success;
}
// Kijk of een punt dicht bij het einde van builder ligt
bool CWhipFile::pointnearend(CWhipFile *deze, WT_Units units, WT_Logical_Point & pt2)
{
WT_Logical_Point pt1 = deze->m_builder[deze->m_builder_len - 1];
if (pt1 == pt2) // quick shortcut
return true;
WT_Point3D dwgPt1 = units.transform(pt1);
WT_Point3D dwgPt2 = units.transform(pt2);
double dist = sqrt(pow(dwgPt1.m_x - dwgPt2.m_x, 2) + pow(dwgPt1.m_y - dwgPt2.m_y, 2));
return (dist < deze->m_minMergeDistance); // Minder dan een cm
}
// Kijk of builder nu een gesloten contour vormt.
// Zo ja voeg hem dan toe (mits groot genoeg) en reset builder
void CWhipFile::test_builder_now_complete(CWhipFile *deze, WT_Units &units)
{
if (deze->m_builder_len > 3 && pointnearend(deze, units, deze->m_builder[0])) // nu closed? Dan toevoegen!
{
CSLNKContourImpl *myContour = new CSLNKContourImpl(deze->m_builder_len, deze->m_builder, WD_True, units);
myContour->m_DWGArea = PolygonArea(myContour, units);
WT_Point3D dwgPt = units.transform(myContour->points()[0]);
myTRACE("\nMerge contour with area %8.0f (%8.2fm2) starting DWF(%3d %d,%d) DWG(%.3f,%.3f)",
myContour->m_DWGArea, myContour->m_DWGArea / 1e6,
myContour->count(),
myContour->points()[0].m_x, myContour->points()[0].m_y,
dwgPt.m_x, dwgPt.m_y);
if (myContour->m_DWGArea >= deze->m_minContSize)
deze->m_SLNKContouren.Add(myContour);// Doet uiteindelijk wel een delete op myContour
else
{
myTRACE(" te klein bevonden");
delete myContour;
}
deze->m_builder_len = 0; // En resetten
}
}
// Punt op arc van sr (start radian) naar er (end radian) met factor tussen 0 en 1
WT_Logical_Point radiuspoint(WT_Logical_Point &center, double radius, double sr, double er, double factor)
{
double angle = sr + (er - sr) * factor;
return WT_Logical_Point (center.m_x + myRound(radius * cos(angle)),
center.m_y + myRound(radius * sin(angle)));
}
void arc2poly(WT_Logical_Point builder[], int &builder_len,
WT_Outline_Ellipse & outlineEllipse, bool reverse = false)
{
double sr = outlineEllipse.start_radian();
double er = outlineEllipse.end_radian();
if (reverse)
{
double h = sr;
sr = er;
er = h;
}
double radius = outlineEllipse.major();
int arcsteps = myRound(abs (er - sr) / TWO_PI * 16); // 16 segmenten voor een hele cirkel
for (int i = 1; i < arcsteps; i++)
builder[builder_len++] = radiuspoint(outlineEllipse.position(), radius, sr, er, ((double) i) / arcsteps);
}
WT_Result CWhipFile::my_process_outlineEllipse(WT_Outline_Ellipse & outlineEllipse, WT_File & file)
{
CWhipFile *deze = (CWhipFile *)file.heuristics().user_data();
if (!deze->m_contLayerActive)
return WT_Result::Success; // Wrong layer
if (deze->m_minMergeDistance < 0)
return WT_Result::Success; // We doen niet aan builden
WT_Units units = fixUnits(file.rendition().viewport().viewport_units());
WT_Point3D dwgPt = units.transform(outlineEllipse.position());
myTRACE("\nFound Ellipse center DWF(%d,%d) DWG(%.3f,%.3f) with minor %d major %d startangle %d endangle %d",
outlineEllipse.position().m_x, outlineEllipse.position().m_y,
dwgPt.m_x, dwgPt.m_y,
outlineEllipse.major(), outlineEllipse.minor(),
outlineEllipse.start(), outlineEllipse.end());
// veronderstel outlineEllipse.major() == outlineEllipse.minor()
double sr = outlineEllipse.start_radian();
double er = outlineEllipse.end_radian();
double radius = outlineEllipse.major();
WT_Logical_Point start = radiuspoint(outlineEllipse.position(), radius, sr, er, 0.0);
WT_Logical_Point end = radiuspoint(outlineEllipse.position(), radius, sr, er, 1.0);
myTRACE("\n start DWF(%d,%d)\n end DWF(%d,%d)",
start.m_x, start.m_y, end.m_x, end.m_y);
if (deze->m_builder_len == 0) // Het is het allereerste segment, bijv. "100976 - C00 - F2-Model-FMH-ARCS.dwf" A-00..BMC
{
deze->m_builder[deze->m_builder_len++] = start; // TODO: Soms moeten we mogelijk start en end nog omwisselen?
arc2poly(deze->m_builder, deze->m_builder_len, outlineEllipse);
deze->m_builder[deze->m_builder_len++] = end;
}
else // Zijn we aan het builden. Kijk of onze ellipse achteraan aansluit
{
if (pointnearend(deze, units, start))
{
//deze->m_builder[deze->m_builder_len++] = start;
arc2poly(deze->m_builder, deze->m_builder_len, outlineEllipse);
deze->m_builder[deze->m_builder_len++] = end;
test_builder_now_complete(deze, units);
}
else if (pointnearend(deze, units, end))
{
//deze->m_builder[deze->m_builder_len++] = end;
arc2poly(deze->m_builder, deze->m_builder_len, outlineEllipse, true /* reverse */);
deze->m_builder[deze->m_builder_len++] = start;
test_builder_now_complete(deze, units);
}
else // Sluit niet aan, reset builder
{
deze->m_builder_len = 0;
}
}
return WT_Result::Success;
}
// This is what AutoCAD seems to create for a normal closed polyline
// but also for the rendition of the character '0'
WT_Result CWhipFile::my_process_polyline(WT_Polyline & polyline, WT_File & file)
@@ -453,7 +589,7 @@ WT_Result CWhipFile::my_process_polyline(WT_Polyline & polyline, WT_File & file)
// (Vigor) DWF's uit ARKEY hebben de onhebbelijke eigenschap dat de contour begint
// met een aanhaallijntje. Dat ondersteunen we dan toch maar.
bool scndIsLast = false;
if (g_SLNKOptions.m_SkipContLeader && polyline.count()>1)
if (g_SLNKOptions.m_SkipContLeader && polyline.count() > 2) // Pas op dat je de 'L' van 2 punten niet negeert (voor builden)
{
scndIsLast = (polyline.points()[1].m_x == polyline.points()[polyline.count()-1].m_x &&
polyline.points()[1].m_y == polyline.points()[polyline.count()-1].m_y);
@@ -461,20 +597,47 @@ WT_Result CWhipFile::my_process_polyline(WT_Polyline & polyline, WT_File & file)
// Houthoff tekening 1082ma50-F-B---04-Model.dwf had voor ruimte 04.44 dat
// de contour nog <20><>n lijntje doorliep na sluiten. Dat ondersteunen we hier maar.
bool xscndIsFirst = false; // een-na-laatste
if (polyline.count()>1)
if (polyline.count() > 2) // Pas op dat je de 'L' van 2 punten niet negeert (voor builden)
{
xscndIsFirst = (polyline.points()[0].m_x == polyline.points()[polyline.count()-2].m_x &&
polyline.points()[0].m_y == polyline.points()[polyline.count()-2].m_y);
}
if (!frstIsLast && !scndIsLast && !xscndIsFirst)
return WT_Result::Success; // Not closed. Who cares
xxxx++;
//WT_Units units=file.rendition().drawing_info().units(); werkt niet goed met paperspace
// Waarom zetten we hier m_contunits eigenlijk nog niet gewoon direct?
WT_Units units = fixUnits(file.rendition().viewport().viewport_units());
// if (polyline.count() == 3 && polyline.points()[0].m_x == 2147470970 && polyline.points()[0].m_y == 22603)
// DebugBreak();
// if (polyline.count() == 2)
// DebugBreak();
if (!frstIsLast && !scndIsLast && !xscndIsFirst) // Niet gesloten. Misschien met builder aan de slag?
{
if (deze->m_minMergeDistance < 0)
return WT_Result::Success; // We doen niet aan builden
if (!pointnearend(deze, units, polyline.points()[0])) //
deze->m_builder_len = 0;
if (deze->m_builder_len == 0 || pointnearend(deze, units, polyline.points()[0]))
{
for (int i = deze->m_builder_len == 0 ? 0 : 1; i < polyline.count(); i++) // eerste eventueel overslaan, die matchte tenslotte
{
deze->m_builder[deze->m_builder_len++] = polyline.points()[i];
}
test_builder_now_complete(deze, units);
}
else
{
deze->m_builder_len = 0; // Anders resetten
}
return WT_Result::Success;
}
xxxx++;
// WD_True as we are going to mess
CSLNKContourImpl *myContour;
if (scndIsLast) // eerste lijntje droppen
@@ -589,8 +752,9 @@ xxxx++;
myContour->m_DWGArea = PolygonArea(myContour, units);
WT_Point3D dwgPt = units.transform(myContour->points()[0]);
myTRACE("\nFound contour with area %8.0f (%8.2fm2) starting DWF(%d,%d) DWG(%.3f,%.3f)",
myTRACE("\nFound contour with area %8.0f (%8.2fm2) starting DWF(%3d %d,%d) DWG(%.3f,%.3f)",
myContour->m_DWGArea, myContour->m_DWGArea/1e6,
myContour->count(),
myContour->points()[0].m_x, myContour->points()[0].m_y,
dwgPt.m_x, dwgPt.m_y);
if (myContour->m_DWGArea >= deze->m_minContSize)
@@ -601,6 +765,8 @@ xxxx++;
delete myContour;
}
deze->m_builder_len = 0; // In ieder geval resetten
return WT_Result::Success;
}
@@ -730,12 +896,21 @@ HRESULT CWhipFile::SerializePlan(WT_File & my_plan_file, myWT_File & my_file, do
}
}
break;
default:
case WT_Object::Informational:
my_plan_file.current_object()->serialize(my_file);
break;
case WT_Object::Wrapper:
// my_plan_file.current_object()->serialize(my_file); // Geeft dubbele (W2D V06.00)
break;
case WT_Object::Definition:
my_plan_file.current_object()->serialize(my_file);
break;
default:
#ifdef _DEBUG
CString s(my_plan_file.file_stats()->descriptions());
//myTRACE("Skipping '%s'\n", s);
CString s(my_plan_file.file_stats()->descriptions());
myTRACE("Skipping '%s'\n", s);
#endif
break;
break;
}
}
@@ -1391,6 +1566,19 @@ STDMETHODIMP CWhipFile::put_minContSize(DOUBLE newVal)
return S_OK;
}
STDMETHODIMP CWhipFile::get_minMergeDistance(DOUBLE* pVal)
{
(*pVal) = m_minMergeDistance;
return S_OK;
}
STDMETHODIMP CWhipFile::put_minMergeDistance(DOUBLE newVal)
{
m_minMergeDistance = newVal;
return S_OK;
}
STDMETHODIMP CWhipFile::get_AddContour(ISLNKContour** pVal)
{
// Je mag eigenlijk geen echt lege contour doorgeven, daar assert de pointset.cpp op?

View File

@@ -88,6 +88,10 @@ private:
myWT_File m_W2DFile;
long m_vdpi;
WT_View m_view; // Initial view
WT_Logical_Point m_builder[1000]; // om lijnstukken aan elkaar te plakken
int m_builder_len;
HRESULT ProcessContouren();
HRESULT SerializePlan(WT_File & my_plan_file, myWT_File & my_file, double scale);
@@ -101,10 +105,13 @@ private:
STDMETHOD(Generate)(myWT_File &my_file);
void read_for_contours();
void processLabels();
static WT_Result my_process_layer (WT_Layer & layer, WT_File & file);
static bool pointnearend(CWhipFile *deze, WT_Units units, WT_Logical_Point & pt2);
static void test_builder_now_complete(CWhipFile *deze, WT_Units &units);
static WT_Result my_process_layer(WT_Layer & layer, WT_File & file);
//static WT_Result my_process_polygon(WT_Polygon & polygon, WT_File & file);
static WT_Result my_process_outlineEllipse(WT_Outline_Ellipse & outlineEllipse, WT_File & file);
static WT_Result my_process_polyline(WT_Polyline & polyline, WT_File & file);
static WT_Result my_process_polytriangle(WT_Polytriangle & polytriangle, WT_File & file);
//static WT_Result my_process_polytriangle(WT_Polytriangle & polytriangle, WT_File & file);
static WT_Result my_process_text (WT_Text & text, WT_File & file);
public:
STDMETHOD(get_hintScale)(DOUBLE* pVal);
@@ -115,6 +122,8 @@ public:
STDMETHOD(return_ContourItem)(CSLNKContourImpl *pContour, ISLNKContour** pVal);
STDMETHOD(get_minContSize)(DOUBLE* pVal);
STDMETHOD(put_minContSize)(DOUBLE newVal);
STDMETHOD(get_minMergeDistance)(DOUBLE* pVal);
STDMETHOD(put_minMergeDistance)(DOUBLE newVal);
STDMETHOD(get_vectorDpi)(LONG* pVal);
STDMETHOD(get_DwgLimits)(IBoundingBox** pVal);
@@ -168,6 +177,8 @@ public:
BOOL m_labelLayerActive;
double m_hintScale; // Kunnen we gebruiken om symbolen te 'geeken'
double m_minContSize; // Minimale oppervlakte om als contour te erkend worden
double m_minMergeDistance; // Minimale afstand om lijnsegmenten te mergen
BOOL m_forFind; // Extra info die we kunnen misbruiken
private: