1065 lines
35 KiB
C++
1065 lines
35 KiB
C++
// WhipFile.cpp : Implementation of CWhipFile
|
|
|
|
#include "stdafx.h"
|
|
#include "myEPlotSection.h"
|
|
#include "WhipFile.h"
|
|
#include "SLNKContour.h"
|
|
|
|
#include "Dwfcore/Mime.h"
|
|
|
|
//
|
|
// WHIPFILE.CPP
|
|
//
|
|
// This file defines class CWhipFile
|
|
// which is mostly concerned with detecting closed contours
|
|
// and merging a Contour file with a planfile. <<= jun 2007: al lang obsolete
|
|
//
|
|
|
|
// CWhipFile
|
|
|
|
WT_Logical_Point star[] = { WT_Logical_Point(-1000, 0),
|
|
WT_Logical_Point( -200, 200),
|
|
WT_Logical_Point( 0, 1000),
|
|
WT_Logical_Point( 200, 200),
|
|
WT_Logical_Point( 1000, 0),
|
|
WT_Logical_Point( 200, -200),
|
|
WT_Logical_Point( 0,-1000),
|
|
WT_Logical_Point( -200, -200),
|
|
WT_Logical_Point(-1000, 0)
|
|
};
|
|
|
|
WT_Logical_Point octa[] = { WT_Logical_Point( 1000, 414),
|
|
WT_Logical_Point( 414, 1000),
|
|
WT_Logical_Point( -414, 1000),
|
|
WT_Logical_Point(-1000, 414),
|
|
WT_Logical_Point(-1000, -414),
|
|
WT_Logical_Point( -414,-1000),
|
|
WT_Logical_Point( 414,-1000),
|
|
WT_Logical_Point( 1000, -414),
|
|
WT_Logical_Point( 1000, 414)
|
|
};
|
|
|
|
CWhipFile::CWhipFile()
|
|
{
|
|
m_FontName.set("Arial");
|
|
m_FontHeight = 400.0;
|
|
m_FontHeightSymbols = 200.0;
|
|
|
|
// Predefine fixed symbols
|
|
CSLNKSymbolDefinition * symb = new CSLNKSymbolDefinition(sizeof(star)/sizeof(star[0]), star);
|
|
m_State.m_SLNKSymbolDefinitions.SetAt("*STAR", symb);
|
|
|
|
symb = new CSLNKSymbolDefinition(sizeof(octa)/sizeof(octa[0]), octa);
|
|
m_State.m_SLNKSymbolDefinitions.SetAt("*OCTAGON", symb);
|
|
}
|
|
|
|
int xxxx;
|
|
STDMETHODIMP CWhipFile::InterfaceSupportsErrorInfo(REFIID riid)
|
|
{
|
|
static const IID* arr[] =
|
|
{
|
|
&IID_IWhipFile
|
|
};
|
|
|
|
for (int i=0; i < sizeof(arr) / sizeof(arr[0]); i++)
|
|
{
|
|
if (InlineIsEqualGUID(*arr[i],riid))
|
|
return S_OK;
|
|
}
|
|
return S_FALSE;
|
|
}
|
|
|
|
// Open de contour file
|
|
STDMETHODIMP CWhipFile::Load(BSTR WhipPath)
|
|
{
|
|
myDoTRACE("\nCWhipFile::Open('%ls')", WhipPath);
|
|
|
|
m_W2DFile.set_filename(WhipPath);
|
|
|
|
return ProcessContouren();
|
|
}
|
|
|
|
|
|
// Set xc = CreateObject("SLNKDWF.DWFFile")
|
|
// xc.Open(dwfFile)
|
|
// Set y = CreateObject("SLNKDWF.WhipFile")
|
|
// y.LoadStream xc.EplotSections.Item(0)
|
|
STDMETHODIMP CWhipFile::LoadStream(VARIANT EPlotStream)
|
|
{
|
|
myDoTRACE("\nCCWhipFile::LoadStream()");
|
|
|
|
if (EPlotStream.vt!=VT_ERROR)
|
|
{
|
|
VARIANT *var2 = &EPlotStream;
|
|
if (var2->vt==(VT_VARIANT|VT_BYREF)) // ByRef
|
|
var2 = (VARIANT *)var2->pvarVal;
|
|
|
|
if (var2->vt==VT_DISPATCH)
|
|
{
|
|
CComQIPtr<IEPlotSection> EPlotSection;
|
|
EPlotSection = var2->pdispVal;
|
|
if (!EPlotSection)
|
|
return E_INVALIDARG;
|
|
else
|
|
{
|
|
m_iEPlotSection = EPlotSection;
|
|
CEPlotSectionImpl *epli;
|
|
m_iEPlotSection->get_EPlotSectionImpl((BYTE **)&epli);
|
|
m_W2DFile.set_eplotsection(epli);
|
|
}
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
return ProcessContouren();
|
|
}
|
|
|
|
HRESULT CWhipFile::ProcessContouren()
|
|
{
|
|
m_W2DFile.set_file_mode(WT_File::File_Read);
|
|
|
|
// Alle callback functies zijn static. Die kunnen de variabele
|
|
// m_State niet benaderen. Daarom maar via set_user_data
|
|
m_W2DFile.heuristics().set_user_data((void *)&m_State);
|
|
|
|
if (m_W2DFile.open() == WT_Result::Success)
|
|
{ xxxx=0;
|
|
CmyTimer xx("Contouren opzoeken");
|
|
m_State.contLayerActive = true;
|
|
m_State.labelLayerActive = true; // Kan bij de eerste laag anders blijken te zijn
|
|
|
|
read_for_contours(); // Zoek eerst alle contouren en labels
|
|
processLabels(); // En verwerk ze daarna
|
|
myDoTRACE("\nFound %d polylines, %d contours and %d labels.", xxxx, m_State.m_SLNKContouren.GetCount(), m_State.m_SLNKLabels.GetCount());
|
|
|
|
m_W2DFile.close(); // closing Input file.
|
|
}
|
|
else
|
|
{
|
|
return myAtlReportError (GetObjectCLSID(), "ERROR CWhipFile:: Unable to open file/stream:");
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::SetLayers(BSTR reContouren, BSTR reLabels)
|
|
{
|
|
myTRACE("\nParsing met contouren %ls", reContouren);
|
|
myTRACE("\nParsing met labels %ls", (LPCTSTR)reLabels);
|
|
if (!m_State.SetLayers(reContouren, reLabels))
|
|
return myAtlReportError (GetObjectCLSID(), "ERROR: Unable to parse Whipfile regLayers");
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// Lagen die over moeten blijven. De rest wordt er uit gestript.
|
|
STDMETHODIMP CWhipFile::SetFilterLayers(BSTR reLayers)
|
|
{
|
|
myTRACE("\nFilter met lagen %ls", reLayers);
|
|
if (!m_State.SetFilterLayers(reLayers))
|
|
return myAtlReportError (GetObjectCLSID(), "ERROR: Unable to parse Whipfile SetFilterLayers");
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void CWhipFile::read_for_contours()
|
|
{
|
|
WT_Result result;
|
|
|
|
m_W2DFile.set_text_action(my_process_text);
|
|
m_W2DFile.set_polyline_action(my_process_polyline);
|
|
|
|
// AutoCAD does not generate polygon's for closed polylines
|
|
// It only does for filled SOLID hatching
|
|
//m_W2DFile.set_polygon_action(my_process_polygon);
|
|
//m_W2DFile.set_polytriangle_action(my_process_polytriangle);
|
|
m_W2DFile.set_layer_action(my_process_layer);
|
|
// Do the actual reading.
|
|
do {
|
|
result = m_W2DFile.process_next_object();
|
|
} while (result == WT_Result::Success);
|
|
|
|
// Nu zijn ze wel een keer bekend, we hebben ze later weer nodig
|
|
m_State.m_contunits=m_W2DFile.rendition().drawing_info().units();
|
|
m_view=m_W2DFile.rendition().rendering_options().view();
|
|
|
|
// 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_polyline_action(WT_Polyline::default_process);
|
|
}
|
|
|
|
// Result: Area in original drawing coordinates
|
|
// Veronderstel dat het 5e punt gelijk is aan het eerste (daarom aan einde delen door 2?)
|
|
double PolygonArea(WT_Point_Set * ps, WT_Units units)
|
|
{
|
|
int i,j;
|
|
double area = 0;
|
|
|
|
for (i=0;i<ps->count();i++) {
|
|
j = (i + 1) % ps->count();
|
|
WT_Point3D dwfPtA = units.transform(ps->points()[i]);
|
|
WT_Point3D dwfPtB = units.transform(ps->points()[j]);
|
|
|
|
area += dwfPtA.m_x * dwfPtB.m_y;
|
|
area -= dwfPtA.m_y * dwfPtB.m_x;
|
|
}
|
|
|
|
area /= 2;
|
|
return(area < 0 ? -area : area);
|
|
}
|
|
|
|
// Iterate all labels and determine in which contour they fall
|
|
void CWhipFile::processLabels()
|
|
{
|
|
for (size_t lbl=0; lbl<m_State.m_SLNKLabels.GetCount(); lbl++)
|
|
{
|
|
WT_Text text = m_State.m_SLNKLabels[lbl];
|
|
|
|
// Find inside which Polygon it falls
|
|
// When multiple: choose smallest!
|
|
CSLNKContourImpl *prevContour = NULL;
|
|
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)
|
|
{
|
|
CSLNKContourImpl *contour= (m_State.m_SLNKContouren[i]);
|
|
if (CSLNKContourImpl::PointInPolygon(text.position(), *contour))
|
|
{
|
|
myTRACE("\n%s with area %8.2fm2", text.string().ascii(), contour->m_DWGArea/1e6);
|
|
if (contour->m_contLabel.length()==0)
|
|
{
|
|
if (prevContour != NULL)
|
|
{
|
|
myTRACE(" Hmm, we hadden al eerder succes");
|
|
if (prevContour->m_DWGArea > contour->m_DWGArea)
|
|
{
|
|
myTRACE(" en we hebben een kleinere. Reset prevContour");
|
|
prevContour->m_contLabel = "";
|
|
prevContour = contour;
|
|
}
|
|
else // Nieuwe contour is niet beter
|
|
{
|
|
contour = prevContour;
|
|
}
|
|
}
|
|
else
|
|
prevContour = contour;
|
|
prevContour->m_contLabel = text.string();
|
|
prevContour->m_Key = text.string().ascii();
|
|
#ifdef SHAKE_FOR_TEST
|
|
if (1||prevContour->m_Label.equals("x706"))
|
|
{
|
|
srand( (unsigned)time( NULL ) );
|
|
int i;
|
|
for (i=0;i<prevContour->count();i++) {
|
|
WT_Logical_Point *pt = &(prevContour->points()[i]);
|
|
int diff = (int)(400); // 0.1% afwijking
|
|
double dx = ((double)rand() / RAND_MAX - 0.5);
|
|
double dy = ((double)rand() / RAND_MAX - 0.5);
|
|
pt->m_x += diff * dx;
|
|
pt->m_y += diff * dy;
|
|
}
|
|
|
|
}
|
|
#endif
|
|
prevContour->m_ptLabel = text.position();
|
|
}
|
|
else
|
|
{
|
|
myTRACE("\nLabel %s with area %8.2fm2", text.string().ascii(), contour->m_DWGArea/1e6);
|
|
if (!strcmp(text.string().ascii(), contour->m_contLabel.ascii()))
|
|
myTRACE(" komt dubbel voor (maar wel dezelfde contour)!");
|
|
else
|
|
myTRACE(" was al bezet door %s", contour->m_contLabel.ascii());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
WT_Result CWhipFile::my_process_layer (WT_Layer & layer, WT_File & file)
|
|
{
|
|
file.rendition().layer() = layer;
|
|
if (layer.layer_name().length()>0) // Anders zittie alleen maar in de weg
|
|
{ // Dat doet de default_process 'fout'
|
|
file.layer_list().add_layer(layer);
|
|
}
|
|
|
|
WT_Integer32 layer_num = layer.layer_num();
|
|
WT_Layer *ll = file.layer_list().find_layer_from_index(layer_num);
|
|
if (ll&& ll->layer_name().ascii())
|
|
{
|
|
CWhipFileState *m_State = (CWhipFileState *)file.heuristics().user_data();
|
|
m_State->labelLayerActive = m_State->labelMatch(ll->layer_name().ascii());
|
|
m_State->contLayerActive = m_State->contMatch(ll->layer_name().ascii());
|
|
}
|
|
|
|
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)
|
|
{
|
|
CWhipFileState *m_State = (CWhipFileState *)file.heuristics().user_data();
|
|
if (!m_State->contLayerActive)
|
|
return WT_Result::Success; // Wrong layer
|
|
|
|
bool frstIsLast = (polyline.points()[0].m_x == polyline.points()[polyline.count()-1].m_x &&
|
|
polyline.points()[0].m_y == polyline.points()[polyline.count()-1].m_y);
|
|
// (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)
|
|
{
|
|
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);
|
|
}
|
|
if (!frstIsLast && !scndIsLast)
|
|
return WT_Result::Success; // Not closed. Who cares
|
|
|
|
xxxx++;
|
|
|
|
WT_Units units=file.rendition().drawing_info().units();
|
|
|
|
// WD_True as we are going to mess
|
|
CSLNKContourImpl *myContour;
|
|
if (scndIsLast) // eerste lijntje droppen
|
|
myContour = new CSLNKContourImpl(polyline.count()-1,polyline.points()+1, WD_True, m_State);
|
|
else
|
|
myContour = new CSLNKContourImpl(polyline.count(),polyline.points(), WD_True, m_State);
|
|
|
|
// A major problem: Sometimes AutoCAD's DWFOUT merges two adjacent polylines
|
|
// into one WT_Polyline. We hate that so we start splitting them again here
|
|
// Note this also happens on rendering of some texts. We don't care about
|
|
// that but cannot detect the difference, so split them as well.
|
|
// TODO: Als een afgesplitste contour uiteindelijk binnen de start contour
|
|
// valt dan hebben we te maken met een eiland dat door een tekenaar
|
|
// gemaakt is. Dan moeten we niet splitsen. Zucht..
|
|
|
|
for (int i=1; i<myContour->count()-2; i++) // -2: Laat normale eindpunt ongemoeid
|
|
{
|
|
if ((myContour->points()[i]).m_x == (myContour->points()[0]).m_x &&
|
|
myContour->points()[i].m_y == myContour->points()[0].m_y
|
|
)
|
|
{ // Van 0..i is al een loop. Trek die er alvast uit
|
|
myTRACE("\nSplit case %d-%d",i,myContour->count());
|
|
// Create a copy of the looping section
|
|
// Sample: i=6, j=2, diff=4 pt
|
|
CSLNKContourImpl *myContour2 = new CSLNKContourImpl(i, myContour->points(), WD_True, m_State);
|
|
myContour2->m_DWGArea = PolygonArea(myContour2, units);
|
|
m_State->m_SLNKContouren.Add(myContour2);
|
|
|
|
// Create a copy of the end section
|
|
CSLNKContourImpl *myContour3 = new CSLNKContourImpl(myContour->count()-i, myContour->points()+i, WD_True, m_State);
|
|
// Delete the old one (seem all together a little overkill)
|
|
delete myContour;
|
|
myContour = myContour3;
|
|
i=0; // vanaf daar verder kijken
|
|
}
|
|
}
|
|
|
|
// Bij akzo 4310 kwam (Alleen AutoCAD 2004) het volgende geval voor.
|
|
// Dat onderkennen we door te testen met het oude algoritme en een twee-punts overlap
|
|
// 0,8--->1
|
|
// | |
|
|
// | v
|
|
// 3,7<--2,6
|
|
// | ^
|
|
// v |
|
|
// 4----->5
|
|
|
|
for (int i=1; i<myContour->count()-1; i++)
|
|
{
|
|
for (int j=0; j<i; j++)
|
|
if (myContour->points()[i] == myContour->points()[j])
|
|
{
|
|
myTRACE("\nSplitsen?");
|
|
if (myContour->points()[i+1] == myContour->points()[j+1])
|
|
{
|
|
myTRACE(" YES");
|
|
// Van j..i is een loop. Trek die er uit
|
|
// myTRACE("\nSplit case %d-%d",i,myContour->count());
|
|
// Create a copy of the looping section
|
|
// Sample: i=6, j=2, diff=4 pt
|
|
CSLNKContourImpl *myContour2 = new CSLNKContourImpl(i-j+1, myContour->points()+j, WD_True, m_State);
|
|
myContour2->m_DWGArea = PolygonArea(myContour2, units);
|
|
m_State->m_SLNKContouren.Add(myContour2);
|
|
|
|
// Close the hole in myContour
|
|
for (int k=j+1; k+i-j<myContour->count(); k++)
|
|
myContour->points()[k]=myContour->points()[k+i-j];
|
|
|
|
// Create a copy of the start section
|
|
CSLNKContourImpl *myContour3 = new CSLNKContourImpl(myContour->count()-(i-j), myContour->points(), WD_True, m_State);
|
|
// Delete the old one (seem all together a little overkill)
|
|
delete myContour;
|
|
myContour = myContour3;
|
|
i=j; // vanaf daar verder kijken
|
|
}
|
|
}
|
|
}
|
|
|
|
// Last (or only) section
|
|
myContour->m_DWGArea = PolygonArea(myContour, units);
|
|
myTRACE("\nFound contour with area %8.2fm2", myContour->m_DWGArea/1e6);
|
|
if (myContour->m_DWGArea >= g_SLNKOptions.m_MinContSize)
|
|
m_State->m_SLNKContouren.Add(myContour);// Doet uiteindelijk wel een delete op myContour
|
|
else
|
|
{
|
|
myTRACE(" te klein bevonden");
|
|
delete myContour;
|
|
}
|
|
|
|
return WT_Result::Success;
|
|
}
|
|
|
|
// Note: For SHX-fonts AutoCAD 2002+ creates an invisible (Text) object
|
|
// which will get used here
|
|
WT_Result CWhipFile::my_process_text (WT_Text & text, WT_File & file)
|
|
{
|
|
CWhipFileState *m_State = (CWhipFileState *)file.heuristics().user_data();
|
|
if (!m_State->labelLayerActive)
|
|
return WT_Result::Success; // Wrong layer
|
|
|
|
m_State->m_SLNKLabels.Add(text);
|
|
return WT_Result::Success;
|
|
}
|
|
|
|
// 'Herschrijf' de plan DWF naar de output
|
|
// Doe eerst de 'header' van de DWF (viewport en zo) en zodra
|
|
// we de eerste drawable tegenkomen doen we de contouren tussendoor
|
|
// zodat die (als ze ingekleurd worden) altijd onderaan liggen
|
|
HRESULT CWhipFile::SerializePlan(WT_File & my_plan_file, myWT_File & my_file, double scale)
|
|
{
|
|
WT_Result result;
|
|
BOOL firstDrawable = true;
|
|
|
|
BOOL CurrentLayerOn = TRUE; // Skip contourlagen
|
|
my_plan_file.set_layer_action(my_process_layer); // Override default processing
|
|
// Do the actual reading.
|
|
|
|
while ((result = my_plan_file.process_next_object()) == WT_Result::Success)
|
|
{
|
|
switch(my_plan_file.current_object()->object_type())
|
|
{
|
|
case WT_Object::Origin_ID:
|
|
break;
|
|
case WT_Object::Drawable:
|
|
if (firstDrawable)
|
|
GenerateContouren(my_plan_file, my_file, scale, true); // Alle 'solid' kleuren
|
|
firstDrawable = false;
|
|
#ifdef _DEBUG
|
|
if (my_plan_file.current_object()->object_id() == WT_Object::Origin_ID
|
|
&& !my_file.heuristics().allow_binary_data()
|
|
)
|
|
{ // I do not understand why but it will assert otherwise
|
|
break;
|
|
}
|
|
#endif
|
|
if (CurrentLayerOn)
|
|
my_plan_file.current_object()->serialize(my_file);
|
|
break;
|
|
case WT_Object::Attribute:
|
|
{
|
|
const WT_Attribute *obj = (WT_Attribute *)my_plan_file.current_object();
|
|
if (obj->object_id() == WT_Object::Layer_ID)
|
|
{ // Sla de oorspronkelijke contour lagen over
|
|
// En ook de lagen die we niet willen
|
|
CurrentLayerOn = TRUE;
|
|
WT_Layer *layer = (WT_Layer *)obj;
|
|
WT_Integer32 layer_num = layer->layer_num();
|
|
if (layer_num==0)
|
|
{ // ARKEY heeft lagen met nummer 0. Dat mag niet volgens de
|
|
// Whip-spec en gaat ook mis (alleen) bij binaire DWF's
|
|
if (my_file.heuristics().allow_binary_data())
|
|
{
|
|
myDoTRACE("\nSkipping layer with invalid number 0");
|
|
break;
|
|
}
|
|
}
|
|
WT_Layer *ll = my_plan_file.layer_list().find_layer_from_index(layer_num);
|
|
if (ll&&
|
|
ll->layer_name().ascii()&&
|
|
(m_State.labelMatch(ll->layer_name().ascii()) ||
|
|
m_State.contMatch(ll->layer_name().ascii()) ||
|
|
!m_State.layerMatch(ll->layer_name().ascii()))
|
|
)
|
|
CurrentLayerOn = FALSE; // Layer object hoeft ook niet meer geserialized
|
|
else
|
|
layer->serialize(my_file);
|
|
}
|
|
else
|
|
{
|
|
#ifdef _DEBUG
|
|
CString s(my_plan_file.file_stats()->descriptions());
|
|
// myTRACE("Attribute '%s'\n", s);
|
|
#endif
|
|
// Hoewel een Attibute gaat hij toch niet via desired_rendition
|
|
// Omdat we weten dat we net uit uit een DWF komen kunnen we best
|
|
// wel rechtstreeks serializen
|
|
// Let wel: desired_rendition is dan niet meer te vertrouwen. Zie @@@
|
|
obj->serialize(my_file);
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
#ifdef _DEBUG
|
|
CString s(my_plan_file.file_stats()->descriptions());
|
|
//myTRACE("Skipping '%s'\n", s);
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
// if (result == WT_Result::End_Of_DWF_Opcode_Found)
|
|
// dwfresult = DwfResult::Success;
|
|
|
|
// TODO: desired_rendition klopt nu niet meer met de daadwerkelijke rendition?
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// Extra saveas wrapper om met __try een eventuele Win32 exception ook op te vangen
|
|
STDMETHODIMP CWhipFile::SaveAs(BSTR WhipPath)
|
|
{
|
|
myTRACE("\nAbout to save into %ls with plan", (LPCTSTR)WhipPath);
|
|
|
|
__try {
|
|
return SaveAs2(WhipPath);
|
|
}
|
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
DWORD exCode = GetExceptionCode();
|
|
myDoTRACE("\nUnhandled Win32 exception 0x%x in CWhipFile::SaveAs", exCode);
|
|
char err[128];
|
|
sprintf(err, "\nUnhandled Win32 exception 0x%x", exCode);
|
|
|
|
return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::SaveAs('%ls')\n%s", (LPCSTR)WhipPath, err);
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::SaveAs2(BSTR WhipPath)
|
|
{
|
|
try {
|
|
myWT_File my_file;
|
|
my_file.set_filename(WhipPath);
|
|
return Generate(my_file);
|
|
}
|
|
catch (WT_Result::Enum e)
|
|
{
|
|
CString err;
|
|
err.Format("\nInternal error WT_Result::Enum %d",e);
|
|
return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::SaveAs('%ls')\n%s", (LPCSTR)WhipPath, err);
|
|
}
|
|
catch (CString &err)
|
|
{
|
|
return myAtlReportError (GetObjectCLSID(), err);
|
|
}
|
|
}
|
|
|
|
// Altijd hoogte 1000, echte fontheight gaf overflow bij SDU
|
|
class tempFontDC
|
|
{
|
|
public:
|
|
tempFontDC(WT_String m_FontName)
|
|
{
|
|
HDC tempDC = CreateDC("DISPLAY",NULL,NULL,NULL);
|
|
m_DC = CreateCompatibleDC ( tempDC );
|
|
DeleteDC(tempDC);
|
|
|
|
LOGFONT lf;
|
|
memset(&lf, 0, sizeof(LOGFONT)); // clear out structure.
|
|
strncpy(lf.lfFaceName, m_FontName.ascii(), LF_FACESIZE);
|
|
lf.lfHeight = -FONT_SIZER;
|
|
fnt = CreateFontIndirect(&lf);
|
|
HGDIOBJ oldfont = SelectObject(m_DC, fnt);
|
|
}
|
|
|
|
~tempFontDC()
|
|
{
|
|
// Opruimen
|
|
DeleteObject(fnt);
|
|
DeleteDC(m_DC);
|
|
}
|
|
inline operator const HDC()
|
|
{ return m_DC; }
|
|
private:
|
|
HDC m_DC;
|
|
HFONT fnt;
|
|
};
|
|
|
|
bool CWhipFile::GenerateSymbols(myWT_File &my_file)
|
|
{
|
|
double scale = m_State.m_contunits.application_to_dwf_transform()(0,0);
|
|
// TODO: Echt uniek layernum (en URL num) bepalen
|
|
my_file.desired_rendition().layer() = WT_Layer(my_file, 1000, "SLNK Symbols");
|
|
|
|
for (size_t i=0; i<m_State.m_SLNKSymbols.GetCount(); i++)
|
|
{
|
|
CSLNKSymbolImpl *symbol= m_State.m_SLNKSymbols[i];
|
|
if (symbol->m_symbolName == "" || !m_State.m_SLNKSymbolDefinitions.Lookup(symbol->m_symbolName))
|
|
symbol->serialize(my_file, m_State.m_contunits, NULL, m_State.m_hintScale);
|
|
else
|
|
{
|
|
#ifdef _DEBUG
|
|
WT_Comments cmt;
|
|
CString s; s.Format("About to insert symbol %s", symbol->m_symbolName);
|
|
cmt.set(s);
|
|
cmt.serialize(my_file);
|
|
#endif
|
|
symbol->serialize(my_file, m_State.m_contunits, m_State.m_SLNKSymbolDefinitions[symbol->m_symbolName], m_State.m_hintScale);
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool CWhipFile::GenerateSymbolLabels(myWT_File &my_file)
|
|
{
|
|
double scale = m_State.m_contunits.application_to_dwf_transform()(0,0);
|
|
// Zet een DC op om bij 'Center' de afmetingen van de tekst te kunnen bepalen
|
|
int fontheight= myRound(m_FontHeightSymbols * scale);
|
|
tempFontDC myDC(m_FontName);
|
|
|
|
WT_Font myfont;
|
|
myfont.font_name() = m_FontName;
|
|
myfont.height() = fontheight;
|
|
my_file.desired_rendition().font() = my_file.rendition().font() = myfont;
|
|
myfont.serialize(my_file); // Vertrouw niets. Expliciete serialize. Zie @@@
|
|
|
|
WT_Color clr(255,255,255,0); //Teksten wit
|
|
my_file.desired_rendition().color() = my_file.rendition().color() = clr;
|
|
clr.serialize(my_file); // Vertrouw niets. Expliciete serialize. Zie @@@
|
|
|
|
// TODO: Echt uniek layernum (en URL num) bepalen
|
|
my_file.desired_rendition().layer() = WT_Layer(my_file, 1001, "SLNK Symbol Labels");
|
|
for (size_t i=0; i<m_State.m_SLNKSymbols.GetCount(); i++)
|
|
{
|
|
CSLNKSymbolImpl *symbol= m_State.m_SLNKSymbols[i];
|
|
// Pas op dat de WT_Polygon nog niet getransformeerd is!
|
|
// Dat maakt LABEL_CENTROID berekeningen tricky....
|
|
// Tegenwoordig: CSLNKSymbolImpl::serialize heeft de contour al getransformeerd
|
|
WT_Logical_Point center = m_State.m_contunits.transform(WT_Point3D(symbol->m_dwgX, symbol->m_dwgY));
|
|
symbol->m_SLNKContour.m_ptLabel = center;
|
|
symbol->m_SLNKContour.SerializeLabel(my_file, CSLNKContourImpl::LABEL_OUTSIDEBOTTOM, fontheight, myDC);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// Schrijf alle uitgerekende contouren naar het DWF bestand
|
|
// Deze functie wordt twee keer aangeroepen
|
|
// Heel vroeg (voor de plattegrond) worden alle contouren met een solid kleur
|
|
// wegeschreven. Die komen dan helemaal onderop. Ze zouden anders afdekken
|
|
// In de tweede slag komen alle transparante contouren. Die komen na de
|
|
// plattegrond zodat de plattegrond doorschijnt.
|
|
bool CWhipFile::GenerateContouren(WT_File &my_planfile, myWT_File &my_file,
|
|
double scale, BOOL solidOnly)
|
|
{
|
|
// Zorg dat we zelf neutraal blijven
|
|
WT_Layer keepLayer = my_planfile.rendition().layer();
|
|
WT_Color keepColor = my_planfile.rendition().color();
|
|
|
|
// Vertrouw de huidige rendition niet!
|
|
WT_Color().serialize(my_file);
|
|
|
|
//Store the current object node hoewel die echt null zal zijn....
|
|
WT_Object_Node current_node = my_file.desired_rendition().object_node();
|
|
|
|
// TODO: Echt uniek layernum (en URL num) bepalen
|
|
my_file.desired_rendition().layer() = WT_Layer(my_file, 1002, "SLNK Contours");
|
|
|
|
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)
|
|
{
|
|
CSLNKContourImpl *contour= m_State.m_SLNKContouren[i];
|
|
my_file.desired_rendition().line_weight() = myRound(10 * scale);
|
|
contour->serialize(my_file, solidOnly);
|
|
}
|
|
my_file.desired_rendition().object_node() = current_node;
|
|
|
|
my_file.desired_rendition().line_weight() = 0; // Voor als er later bijvoorbeeld nog symbolen komen
|
|
|
|
my_file.desired_rendition().layer() = my_file.rendition().layer() = keepLayer;
|
|
if (keepLayer.layer_num()) keepLayer.serialize(my_file); // Zeker terugzetten
|
|
my_file.desired_rendition().color() = my_file.rendition().color() = keepColor;
|
|
keepColor.serialize(my_file); // Zeker terugzetten
|
|
return true;
|
|
}
|
|
|
|
bool CWhipFile::GenerateLabels(WT_File &my_planfile, myWT_File &my_file, double scale)
|
|
{
|
|
// Zorg dat we zelf neutraal blijven
|
|
WT_Layer keepLayer = my_planfile.rendition().layer();
|
|
WT_Color keepColor = my_planfile.rendition().color();
|
|
|
|
// TODO: Echt uniek layernum (en URL num) bepalen
|
|
my_file.desired_rendition().layer() = WT_Layer(my_file, 1003, "SLNK Labels");
|
|
|
|
// Zet een DC op om bij 'Center' de afmetingen van de tekst te kunnen bepalen
|
|
int fontheight= myRound(m_FontHeight * scale);
|
|
tempFontDC myDC(m_FontName);
|
|
|
|
WT_Font myfont;
|
|
myfont.font_name() = m_FontName;
|
|
myfont.height() = fontheight;
|
|
my_file.desired_rendition().font() = my_file.rendition().font() = myfont;
|
|
myfont.serialize(my_file); // Vertrouw niets. Expliciete serialize. Zie @@@
|
|
|
|
// En nu nog een keer alle teksten
|
|
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)
|
|
{
|
|
CSLNKContourImpl *contour= m_State.m_SLNKContouren[i];
|
|
|
|
// Een polyline hebben we nu niet nodig
|
|
if (contour->m_contLabel.length()!=0 && contour->m_ExtraLabel != "")
|
|
{ // We have got a proper label/contour
|
|
// Alle teksten tekenen
|
|
contour->SerializeLabel(my_file, m_LabelPos, fontheight, myDC);
|
|
}
|
|
}
|
|
|
|
my_file.desired_rendition().layer() = my_file.rendition().layer() = keepLayer;
|
|
if (keepLayer.layer_num()) keepLayer.serialize(my_file); // Zeker terugzetten
|
|
my_file.desired_rendition().color() = my_file.rendition().color() = keepColor;
|
|
keepColor.serialize(my_file); // Zeker terugzetten
|
|
|
|
return true;
|
|
}
|
|
|
|
// We hebben de contouren bepaald. Genereer daarvoor nu nieuwe DWF-primitieven
|
|
// In het bijzonder kennen we er een kleurtje aan toe en plaatsen wel de labels (opnieuw)
|
|
STDMETHODIMP CWhipFile::Generate(myWT_File &my_file)
|
|
{
|
|
// Bepaal de te gebruiken hoogte in Logical Points
|
|
|
|
double scale = m_State.m_contunits.application_to_dwf_transform()(0,0);
|
|
myDoTRACE("\nSchaal: %.2f", scale);
|
|
|
|
WT_Result result;
|
|
|
|
my_file.set_file_mode(WT_File::File_Write);
|
|
#ifdef _DEBUG
|
|
my_file.heuristics().set_allow_binary_data(WD_False);
|
|
#endif
|
|
// Zal niet zo snel meer gebeuren maar we willen het zeker niet
|
|
my_file.heuristics().set_allow_drawable_merging(WD_False);
|
|
// Let op: De viewer kan 60-file niet zo maar lezen, dat moet naar packed-DWF
|
|
// Later: viewer 6.5 kan gewoon een W2D file tonen
|
|
// Let op: bij versie 55 worden Node's niet weggeschreven
|
|
// my_file.heuristics().set_target_version(55);
|
|
if (my_file.open() != WT_Result::Success)
|
|
{
|
|
return myAtlReportError (GetObjectCLSID(), "ERROR: Unable to open file for writing: %s", my_file.filename().ascii());
|
|
ATLASSERT(false);
|
|
}
|
|
|
|
// Symbolen worden mogelijk geplaatst net buiten onze coordinatenruimte (met name X)
|
|
// Dat gaf clipping problemen.
|
|
// Daarom verplaatsen we alles in onze coordinatenruimte naar links/onder (0,0)
|
|
WT_Logical_Point lshift(-(max(0,this->m_view.view().m_min.m_x)),
|
|
-(max(0,this->m_view.view().m_min.m_y))); // Iets minder clipping van INT_MAX
|
|
// Contouren hebben we ondertussen al wel/
|
|
// Nu nog een keer door de DWF om de rest te kopieren naar de output
|
|
m_W2DFile.set_file_mode(WT_File::File_Read);
|
|
my_file.heuristics().set_apply_transform(WD_False);
|
|
myTRACE("\nAbout to open plan");
|
|
if (m_W2DFile.open() == WT_Result::Success)
|
|
{
|
|
#ifdef _DEBUG
|
|
WT_Comments cmt;
|
|
cmt.set("About to insert planfile");
|
|
cmt.serialize(my_file);
|
|
#endif
|
|
// TODO: Dit moet uit de originele PlanDWF z'n Manifest/Paper komen
|
|
|
|
int keep=my_file.heuristics().target_version();
|
|
// Even background ondersteunen
|
|
my_file.heuristics().set_target_version(55);
|
|
WT_Background bg(WT_Color(0,0,0));
|
|
bg.serialize(my_file);
|
|
my_file.heuristics().set_target_version(keep);
|
|
|
|
my_file.heuristics().set_transform(WT_Transform (lshift, 1.0, 1.0, 0));
|
|
my_file.heuristics().set_apply_transform(true);
|
|
|
|
{
|
|
CmyTimer tm("Serializing plan");
|
|
SerializePlan(m_W2DFile, my_file, scale); // Heeft eventueel een GenerateContouren in zich!
|
|
}
|
|
#ifdef _DEBUG
|
|
cmt.set("Plan is serialized");
|
|
cmt.serialize(my_file);
|
|
#endif
|
|
myTRACE("\nPlan is serialized");
|
|
m_W2DFile.close();
|
|
}
|
|
else
|
|
{
|
|
myTRACE("\nKon plan niet openen");
|
|
return myAtlReportError (GetObjectCLSID(), "ERROR: Unable to open plan file");
|
|
}
|
|
|
|
myTRACE("\nAbout to generate Contouren");
|
|
// Twee loops. Eerst alle contouren (en vlakvullingen), daarna pas
|
|
// de teksten. Zodoende zijn de teksten altijd leesbaar
|
|
GenerateContouren(m_W2DFile, my_file, scale, false); // Alle transparante kleuren
|
|
//merging geeft vreemd effect op de contouren die we om symbolen tekenen in _DEBUG mode
|
|
// dan worden die contouren niet meer meegeschaalt? TODO: Uitzoeken
|
|
//my_file.heuristics().set_allow_drawable_merging(WD_True); // Voor symbolen kan het (na verschalen) wel schelen
|
|
GenerateSymbols(my_file); // Ook alle contouren van symbolen
|
|
GenerateSymbolLabels(my_file);
|
|
GenerateLabels(m_W2DFile, my_file, scale);
|
|
|
|
myTRACE("\nAbout to close");
|
|
//Restore the saved object node.
|
|
my_file.desired_rendition().fill() = WD_False;
|
|
my_file.close();
|
|
|
|
myTRACE("\nDone saving");
|
|
return S_OK;
|
|
}
|
|
|
|
// mei 2007: DEPRECATED
|
|
// Lege Identlabel zet alle labels op de extralabel+default
|
|
STDMETHODIMP CWhipFile::SetLabel(BSTR IdentLabel, BSTR ExtraLabel)
|
|
{
|
|
try {
|
|
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)
|
|
{
|
|
CSLNKContourImpl *contour= m_State.m_SLNKContouren[i];
|
|
if (contour->m_contLabel.length()>0)
|
|
{
|
|
if (contour->m_contLabel.equals(IdentLabel) || SysStringLen(IdentLabel) == 0)
|
|
{
|
|
contour->m_ExtraLabel = ExtraLabel;
|
|
}
|
|
|
|
if (SysStringLen(IdentLabel) == 0)
|
|
contour->m_ExtraLabel += contour->m_contLabel.ascii();
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
catch (WT_Result::Enum e)
|
|
{
|
|
CString err;
|
|
err.Format("\nInternal error WT_Result::Enum %d",e);
|
|
return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::SetLabel('%ls')\n%s", (LPCSTR)IdentLabel, err);
|
|
}
|
|
}
|
|
|
|
// mei 2007: DEPRECATED
|
|
// Lege Identlabel zet alle ruimtes op dezelfde kleur
|
|
STDMETHODIMP CWhipFile::SetColor(BSTR IdentLabel, ULONG rgb, BYTE Alpha /*=0*/)
|
|
{
|
|
try {
|
|
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)
|
|
{
|
|
CSLNKContourImpl *contour= m_State.m_SLNKContouren[i];
|
|
if (contour->m_contLabel.length()>0 &&
|
|
(SysStringLen(IdentLabel) == 0 || contour->m_contLabel.equals(IdentLabel)))
|
|
{
|
|
int b=rgb%256;
|
|
int g=(rgb>>8)%256;
|
|
int r=(rgb>>16)%256;
|
|
contour->m_Color.set(r, g, b, Alpha);
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
catch (WT_Result::Enum e)
|
|
{
|
|
CString err;
|
|
err.Format("\nInternal error WT_Result::Enum %d",e);
|
|
return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::SetColor('%ls')\n%s", (LPCSTR)IdentLabel, err);
|
|
}
|
|
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::SetLabelFont(BSTR FontName, DOUBLE FontHeight, DOUBLE FontHeightSymbols)
|
|
{
|
|
m_FontName.set(FontName);
|
|
m_FontHeight = FontHeight;
|
|
m_FontHeightSymbols = (FontHeightSymbols>0)?FontHeightSymbols:FontHeight;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::SetLabelPosition(BYTE LabelPos)
|
|
{
|
|
switch (LabelPos)
|
|
{
|
|
case 1: m_LabelPos = CSLNKContourImpl::LABEL_DEFAULT; break;
|
|
case 2: m_LabelPos = CSLNKContourImpl::LABEL_CENTROID; break;
|
|
case 3: m_LabelPos = CSLNKContourImpl::LABEL_TOPLEFT; break;
|
|
default: m_LabelPos = CSLNKContourImpl::LABEL_DEFAULT;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::get_ContoursXML(BSTR* pVal)
|
|
{
|
|
DWFCore::DWFBufferOutputStream XMLProps(1024);
|
|
|
|
DWFUUID _oUUID;
|
|
DWFXMLSerializer XML(_oUUID);
|
|
XML.attach(XMLProps);
|
|
XML.startElement( L"Contours", L"SLNKDWF" );
|
|
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)
|
|
{
|
|
CSLNKContourImpl *contour= m_State.m_SLNKContouren[i];
|
|
contour->serializeXML(XML, 0);
|
|
}
|
|
XML.endElement();
|
|
XML.detach();
|
|
|
|
CComBSTR bstrString((int)XMLProps.bytes(), (LPCSTR)XMLProps.buffer());
|
|
return bstrString.CopyTo(pVal);
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::get_AddSymbol(DOUBLE dwgX, DOUBLE dwgY, BSTR symbolName, IUnknown** pVal)
|
|
{
|
|
CString name(symbolName);
|
|
|
|
myTRACE("\nAdding symbol %s at %.2f,%.2f", name, dwgX, dwgY);
|
|
|
|
CSLNKSymbolImpl *mySymbol = new CSLNKSymbolImpl(dwgX, dwgY, &m_State);
|
|
m_State.m_SLNKSymbols.Add(mySymbol);
|
|
|
|
// Als resultaat leveren we een COM object op waar je eventueel de rest van
|
|
// de properties op kunt zetten
|
|
CComObject<CSLNKSymbol> *theSymbol;
|
|
HRESULT hr = CComObject<CSLNKSymbol>::CreateInstance(&theSymbol);
|
|
if(FAILED(hr)) return hr;
|
|
|
|
theSymbol->AddRef();
|
|
hr = theSymbol->QueryInterface(IID_ISLNKSymbol, (void **)pVal);
|
|
theSymbol->SetParent(this); // Zodat scope blijft
|
|
theSymbol->Release();
|
|
if(FAILED(hr)) return hr;
|
|
theSymbol->SetImpl(mySymbol); // Heel belangrijk: zet de implementatie waar we een interface op bieden
|
|
|
|
if (!m_State.m_SLNKSymbolDefinitions.Lookup(name))
|
|
name = "*STAR"; // Die vinden we altijd ja
|
|
ATLASSERT(m_State.m_SLNKSymbolDefinitions.Lookup(name));
|
|
|
|
mySymbol->m_symbolName = name;
|
|
mySymbol->m_SLNKContour.set(m_State.m_SLNKSymbolDefinitions[name]->m_BoundingContour.count(),
|
|
m_State.m_SLNKSymbolDefinitions[name]->m_BoundingContour.points(), true); // TODO: Is copy wel nodig?==>Ja, we gaan ze later transformeren!
|
|
if (name[0] == '*')
|
|
{
|
|
mySymbol->m_SLNKContour.m_Color = WT_Color(255,0,0,255);
|
|
mySymbol->m_SLNKContour.m_outlineAlpha = 255; // Anders wordtie helemaal niet getekend?
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::DefineSymbol(BSTR symbolName, VARIANT EPlotStream)
|
|
{
|
|
myTRACE("\nDefining symbol %ls", symbolName);
|
|
if (EPlotStream.vt!=VT_ERROR)
|
|
{
|
|
VARIANT *var2 = &EPlotStream;
|
|
if (var2->vt==(VT_VARIANT|VT_BYREF)) // ByRef
|
|
var2 = (VARIANT *)var2->pvarVal;
|
|
|
|
if (var2->vt==VT_DISPATCH)
|
|
{
|
|
CComQIPtr<IEPlotSection> EPlotSection;
|
|
EPlotSection = var2->pdispVal;
|
|
if (!EPlotSection)
|
|
return E_INVALIDARG;
|
|
else
|
|
{
|
|
CSLNKSymbolDefinition * symb = new CSLNKSymbolDefinition(EPlotSection);
|
|
|
|
CString name(symbolName);
|
|
m_State.m_SLNKSymbolDefinitions.SetAt(name, symb);
|
|
}
|
|
}
|
|
else
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::DefineBitmapSymbol(BSTR symbolName, BSTR symbolPath, double height)
|
|
{
|
|
myTRACE("\nDefining bitmap symbol %ls", symbolName);
|
|
CSLNKSymbolDefinition * symb = new CSLNKSymbolDefinition(CString(symbolPath), height);
|
|
CString name(symbolName);
|
|
m_State.m_SLNKSymbolDefinitions.SetAt(name, symb);
|
|
//return E_INVALIDARG;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
// Merk op: als iemand twee keer dezelfde contour opvraagt maken we twee onafhankelijke
|
|
// SLNKContour objecten aan die beide naar dezelfde CSLNKContourImpl wijzen
|
|
// Het maakt verder weinig uit en is wel gemakkelijker (toch?)
|
|
STDMETHODIMP CWhipFile::get_Contour(BSTR IdentLabel, IUnknown** pVal)
|
|
{
|
|
try {
|
|
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)
|
|
{
|
|
CSLNKContourImpl *contour= m_State.m_SLNKContouren[i];
|
|
if (contour->m_contLabel.length()>0 && contour->m_contLabel.equals(IdentLabel))
|
|
{
|
|
CComObject<CSLNKContour> *theContour;
|
|
HRESULT hr = CComObject<CSLNKContour>::CreateInstance(&theContour);
|
|
if(FAILED(hr)) return hr;
|
|
|
|
theContour->AddRef();
|
|
hr = theContour->QueryInterface(IID_ISLNKContour, (void **)pVal);
|
|
theContour->SetParent(this);
|
|
theContour->Release();
|
|
if(FAILED(hr)) return hr;
|
|
theContour->SetImpl(contour); // Heel belangrijk: zet de implementatie waar we een interface op bieden
|
|
|
|
return S_OK; // Wel gevonden
|
|
}
|
|
}
|
|
return S_OK; // Niet gevonden. Automatisch NULL?
|
|
}
|
|
catch (WT_Result::Enum e)
|
|
{
|
|
CString err;
|
|
err.Format("\nInternal error WT_Result::Enum %d",e);
|
|
return myAtlReportError (GetObjectCLSID(), "\nCWhipFile::get_Contour('%ls')\n%s", (LPCSTR)IdentLabel, err);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::get_hintScale(DOUBLE* pVal)
|
|
{
|
|
(*pVal) = m_State.m_hintScale;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::put_hintScale(DOUBLE newVal)
|
|
{
|
|
m_State.m_hintScale = newVal;
|
|
myTRACE("\nhintScale set to %.6f", newVal);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
STDMETHODIMP CWhipFile::get_FindInContour(DOUBLE dwgX, DOUBLE dwgY, BSTR* pVal)
|
|
{
|
|
CString result;
|
|
WT_Point3D insertion(dwgX, dwgY);
|
|
WT_Logical_Point LPInsertion = m_State.m_contunits.transform(WT_Point3D(dwgX, dwgY));
|
|
|
|
for (size_t i=0; i<m_State.m_SLNKContouren.GetCount(); i++)
|
|
{
|
|
CSLNKContourImpl *contour= m_State.m_SLNKContouren[i];
|
|
if (contour->m_contLabel.length()>0)
|
|
if (CSLNKContourImpl::PointInPolygon(LPInsertion, *contour))
|
|
{
|
|
result = contour->m_contLabel;
|
|
(*pVal) = result.AllocSysString();
|
|
}
|
|
}
|
|
return S_OK;
|
|
} |