Geometrize  1.0
An application for geometrizing images into geometric primitives
Public Member Functions | Private Member Functions | Static Private Member Functions | Private Attributes | List of all members
geometrize::task::ImageTask::ImageTaskImpl Class Reference
Collaboration diagram for geometrize::task::ImageTask::ImageTaskImpl:
Collaboration graph
[legend]

Public Member Functions

 ImageTaskImpl (ImageTask *pQ, const std::string &displayName, Bitmap &bitmap, Qt::ConnectionType workerConnectionType)
 
 ImageTaskImpl (ImageTask *pQ, const std::string &displayName, Bitmap &bitmap, const Bitmap &initial, Qt::ConnectionType workerConnectionType)
 
 ~ImageTaskImpl ()
 
ImageTaskImploperator= (const ImageTaskImpl &)=delete
 
 ImageTaskImpl (const ImageTaskImpl &)=delete
 
geometrize::script::GeometrizerEnginegetGeometrizer ()
 
Bitmap & getTarget ()
 
Bitmap & getCurrent ()
 
const Bitmap & getTarget () const
 
const Bitmap & getCurrent () const
 
std::uint32_t getWidth () const
 
std::uint32_t getHeight () const
 
std::string getDisplayName () const
 
std::size_t getTaskId () const
 
bool isStepping () const
 
void stepModel ()
 
void drawShape (const std::shared_ptr< geometrize::Shape > shape, const geometrize::rgba color)
 
void drawBackgroundRectangle (const geometrize::rgba color)
 
void modelWillStep ()
 
void modelDidStep (const std::vector< geometrize::ShapeResult > shapes)
 
preferences::ImageTaskPreferencesgetPreferences ()
 
void setPreferences (const preferences::ImageTaskPreferences preferences)
 

Private Member Functions

void init (const Qt::ConnectionType connectionType)
 
void connectSignals (const Qt::ConnectionType connectionType)
 
void disconnectAll ()
 

Static Private Member Functions

static std::size_t getId ()
 

Private Attributes

ImageTaskq
 
preferences::ImageTaskPreferences m_preferences
 
const std::string m_displayName
 

Runtime configuration parameters for the runner.

More...
 
const std::size_t m_id
 

The display name of the image task.

More...
 
QThread m_workerThread
 

A unique id for the image task.

More...
 
ImageTaskWorker m_worker
 

Thread that the image task worker runs on.

More...
 
geometrize::script::GeometrizerEngine m_geometrizer
 

The image task worker.

More...
 

Constructor & Destructor Documentation

◆ ImageTaskImpl() [1/3]

geometrize::task::ImageTask::ImageTaskImpl::ImageTaskImpl ( ImageTask pQ,
const std::string &  displayName,
Bitmap &  bitmap,
Qt::ConnectionType  workerConnectionType 
)
inline
36  :
37  q{pQ}, m_preferences{}, m_displayName{displayName}, m_id{getId()}, m_worker{bitmap}
38  {
39  init(workerConnectionType);
40  }

◆ ImageTaskImpl() [2/3]

geometrize::task::ImageTask::ImageTaskImpl::ImageTaskImpl ( ImageTask pQ,
const std::string &  displayName,
Bitmap &  bitmap,
const Bitmap &  initial,
Qt::ConnectionType  workerConnectionType 
)
inline
42  :
43  q{pQ}, m_preferences{}, m_displayName{displayName}, m_id{getId()}, m_worker{bitmap, initial}
44  {
45  init(workerConnectionType);
46  }

◆ ~ImageTaskImpl()

geometrize::task::ImageTask::ImageTaskImpl::~ImageTaskImpl ( )
inline
49  {
50  disconnectAll();
51 
52  m_workerThread.quit();
53  if(!m_workerThread.wait(1000)) {
54  m_workerThread.terminate();
55  m_workerThread.wait();
56  }
57  }
Here is the call graph for this function:

◆ ImageTaskImpl() [3/3]

geometrize::task::ImageTask::ImageTaskImpl::ImageTaskImpl ( const ImageTaskImpl )
delete

Member Function Documentation

◆ connectSignals()

void geometrize::task::ImageTask::ImageTaskImpl::connectSignals ( const Qt::ConnectionType  connectionType)
inlineprivate
274  {
275  q->connect(q, &ImageTask::signal_step, &m_worker, &ImageTaskWorker::step, connectionType);
276  q->connect(q, &ImageTask::signal_drawShape, &m_worker, &ImageTaskWorker::drawShape, connectionType);
277  q->connect(&m_worker, &ImageTaskWorker::signal_willStep, q, &ImageTask::modelWillStep, Qt::BlockingQueuedConnection);
278  q->connect(&m_worker, &ImageTaskWorker::signal_didStep, q, &ImageTask::modelDidStep, Qt::BlockingQueuedConnection);
279  }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ disconnectAll()

void geometrize::task::ImageTask::ImageTaskImpl::disconnectAll ( )
inlineprivate
Here is the call graph for this function:
Here is the caller graph for this function:

◆ drawBackgroundRectangle()

void geometrize::task::ImageTask::ImageTaskImpl::drawBackgroundRectangle ( const geometrize::rgba  color)
inline
208  {
209  const std::int32_t w = m_worker.getTarget().getWidth();
210  const std::int32_t h = m_worker.getTarget().getHeight();
211  const std::shared_ptr<geometrize::Rectangle> rectangle = std::make_shared<geometrize::Rectangle>(0, 0, w, h);
212  rectangle->rasterize = [w, h](const geometrize::Shape& s) { return geometrize::rasterize(static_cast<const geometrize::Rectangle&>(s), 0, 0, w, h); };
213 
214  emit q->signal_drawShape(rectangle, color);
215  }
Here is the call graph for this function:

◆ drawShape()

void geometrize::task::ImageTask::ImageTaskImpl::drawShape ( const std::shared_ptr< geometrize::Shape >  shape,
const geometrize::rgba  color 
)
inline
203  {
204  emit q->signal_drawShape(shape, color);
205  }

◆ getCurrent() [1/2]

Bitmap& geometrize::task::ImageTask::ImageTaskImpl::getCurrent ( )
inline
73  {
74  return m_worker.getCurrent();
75  }
Here is the call graph for this function:

◆ getCurrent() [2/2]

const Bitmap& geometrize::task::ImageTask::ImageTaskImpl::getCurrent ( ) const
inline
83  {
84  return m_worker.getCurrent();
85  }
Here is the call graph for this function:

◆ getDisplayName()

std::string geometrize::task::ImageTask::ImageTaskImpl::getDisplayName ( ) const
inline
98  {
99  return m_displayName;
100  }

◆ getGeometrizer()

geometrize::script::GeometrizerEngine& geometrize::task::ImageTask::ImageTaskImpl::getGeometrizer ( )
inline
63  {
64  return m_geometrizer;
65  }

◆ getHeight()

std::uint32_t geometrize::task::ImageTask::ImageTaskImpl::getHeight ( ) const
inline
93  {
94  return m_worker.getCurrent().getHeight();
95  }
Here is the call graph for this function:

◆ getId()

static std::size_t geometrize::task::ImageTask::ImageTaskImpl::getId ( )
inlinestaticprivate
240  {
241  static std::atomic<std::size_t> id{0U};
242  return id++;
243  }

◆ getPreferences()

preferences::ImageTaskPreferences& geometrize::task::ImageTask::ImageTaskImpl::getPreferences ( )
inline
228  {
229  return m_preferences;
230  }

◆ getTarget() [1/2]

Bitmap& geometrize::task::ImageTask::ImageTaskImpl::getTarget ( )
inline
68  {
69  return m_worker.getTarget();
70  }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ getTarget() [2/2]

const Bitmap& geometrize::task::ImageTask::ImageTaskImpl::getTarget ( ) const
inline
78  {
79  return m_worker.getTarget();
80  }
Here is the call graph for this function:

◆ getTaskId()

std::size_t geometrize::task::ImageTask::ImageTaskImpl::getTaskId ( ) const
inline
103  {
104  return m_id;
105  }

◆ getWidth()

std::uint32_t geometrize::task::ImageTask::ImageTaskImpl::getWidth ( ) const
inline
88  {
89  return m_worker.getCurrent().getWidth();
90  }
Here is the call graph for this function:

◆ init()

void geometrize::task::ImageTask::ImageTaskImpl::init ( const Qt::ConnectionType  connectionType)
inlineprivate
246  {
247  const auto& shapeBounds = m_preferences.getImageRunnerOptions().shapeBounds;
248 
249  m_geometrizer.getEngine()->set_global(chaiscript::var(q), "task");
250 
251  const auto [xMin, yMin, xMax, yMax] = geometrize::commonutil::mapShapeBoundsToImage(shapeBounds, getTarget());
252 
253  m_geometrizer.getEngine()->set_global(chaiscript::var(xMin), "xMin");
254  m_geometrizer.getEngine()->set_global(chaiscript::var(yMin), "yMin");
255  m_geometrizer.getEngine()->set_global(chaiscript::var(xMax), "xMax");
256  m_geometrizer.getEngine()->set_global(chaiscript::var(yMax), "yMax");
257 
258  qRegisterMetaType<std::vector<geometrize::ShapeResult>>();
259  qRegisterMetaType<geometrize::ImageRunnerOptions>();
260  qRegisterMetaType<std::function<std::shared_ptr<geometrize::Shape>()>>();
261  qRegisterMetaType<std::shared_ptr<geometrize::Shape>>();
262  qRegisterMetaType<geometrize::rgba>();
263  qRegisterMetaType<geometrize::core::EnergyFunction>();
264  qRegisterMetaType<geometrize::ShapeAcceptancePreconditionFunction>();
265 
266  m_worker.moveToThread(&m_workerThread);
267 
268  connectSignals(connectionType);
269 
270  m_workerThread.start();
271  }
Here is the call graph for this function:

◆ isStepping()

bool geometrize::task::ImageTask::ImageTaskImpl::isStepping ( ) const
inline
108  {
109  return m_worker.isStepping();
110  }
Here is the call graph for this function:

◆ modelDidStep()

void geometrize::task::ImageTask::ImageTaskImpl::modelDidStep ( const std::vector< geometrize::ShapeResult >  shapes)
inline
223  {
224  emit q->signal_modelDidStep(shapes);
225  }

◆ modelWillStep()

void geometrize::task::ImageTask::ImageTaskImpl::modelWillStep ( )
inline
218  {
219  emit q->signal_modelWillStep();
220  }

◆ operator=()

ImageTaskImpl& geometrize::task::ImageTask::ImageTaskImpl::operator= ( const ImageTaskImpl )
delete

◆ setPreferences()

void geometrize::task::ImageTask::ImageTaskImpl::setPreferences ( const preferences::ImageTaskPreferences  preferences)
inline
233  {
234  m_preferences = preferences;
235  emit q->signal_preferencesSet();
236  }

◆ stepModel()

void geometrize::task::ImageTask::ImageTaskImpl::stepModel ( )
inline
113  {
114  const bool isScriptModeEnabled = m_preferences.isScriptModeEnabled();
115  const auto imageRunnerOptions = m_preferences.getImageRunnerOptions();
116 
117  // Install the scripts that are required for the geometrization process
119 
120  // Install the additional precondition scripts to decide whether to accept/reject shapes offered back by the library
121  std::vector<std::pair<std::string, std::string>> addShapePreconditionScripts;
122  for(const auto& script : m_preferences.getScripts()) {
123  if(QString::fromStdString(script.first).startsWith("add_shape_precondition_")) { // NOTE prefix is also used by the scripting widgets elsewhere
124  addShapePreconditionScripts.push_back(std::make_pair(script.first, script.second));
125  }
126  }
127 
128  const auto addShapePreconditionFunction =
129  [this](const std::vector<std::pair<std::string, std::string>>& scripts)
130  -> geometrize::ShapeAcceptancePreconditionFunction
131  {
132  if(scripts.empty()) {
133  return nullptr;
134  }
135 
136  const geometrize::ShapeAcceptancePreconditionFunction g = [this, scripts](double lastScore,
137  double newScore,
138  const geometrize::Shape& shape,
139  const std::vector<geometrize::Scanline>& lines,
140  const geometrize::rgba& color,
141  const geometrize::Bitmap& before,
142  const geometrize::Bitmap& after,
143  const geometrize::Bitmap& target) {
144  std::vector<bool> retValues;
145  try {
146  m_geometrizer.getEngine()->set_global(chaiscript::var(lastScore), "candidateShapeLastScore");
147  m_geometrizer.getEngine()->set_global(chaiscript::var(newScore), "candidateShapeNextScore");
148  m_geometrizer.getEngine()->set_global(chaiscript::var(shape), "candidateShape");
149  m_geometrizer.getEngine()->set_global(chaiscript::var(lines), "candidateScanlines");
150  m_geometrizer.getEngine()->set_global(chaiscript::var(color), "candidateShapeColor");
151  m_geometrizer.getEngine()->set_global(chaiscript::var(before), "beforeBitmap");
152  m_geometrizer.getEngine()->set_global(chaiscript::var(after), "afterBitmap");
153  m_geometrizer.getEngine()->set_global(chaiscript::var(target), "targetBitmap");
154 
155  for(const auto& script : scripts) {
156  retValues.emplace_back(m_geometrizer.getEngine()->eval<bool>(script.second));
157  }
158  return std::all_of(retValues.begin(), retValues.end(), [](const bool b) { return b == true; });
159  } catch(std::exception& e) {
160  std::cout << e.what() << std::endl;
161  }
162  return false;
163  };
164  return g;
165  }(addShapePreconditionScripts);
166 
167  // Opt out of the multithreaded scripts if the engine is disabled (use the default/C++ implementations)
168  if(!isScriptModeEnabled) {
169  emit q->signal_step(imageRunnerOptions, nullptr, nullptr, addShapePreconditionFunction);
170  return;
171  }
172 
173  const auto& target = m_worker.getTarget();
174 
175  const auto bounds = geometrize::commonutil::mapShapeBoundsToImage(imageRunnerOptions.shapeBounds, target);
176 
177  // Scripting is enabled - clone the entire geometrizer engine
178  // This is important because many threads will be working with it when geometrizing shapes
179  // and we don't want to mess with the state of the engine on the main thread while these threads are working with it
180  const auto geometrizerEngineClone = [this]() {
181  auto engine = std::make_shared<geometrize::script::GeometrizerEngine>(m_geometrizer.getEngine()->get_state());
182  engine->installScripts(m_preferences.getScripts());
183  return engine;
184  }();
185 
186  // Pick the shape creation function
187  const auto shapeCreator = [geometrizerEngineClone, imageRunnerOptions, bounds]() {
188  // NOTE - this method uses shared_from_this to keep the engine alive
189  const auto [xMin, yMin, xMax, yMax] = bounds;
190  return geometrizerEngineClone->makeShapeCreator(imageRunnerOptions.shapeTypes, xMin, yMin, xMax, yMax);
191  }();
192 
193  // Pick the energy calculation function
194  const geometrize::core::EnergyFunction energyFunction = [geometrizerEngineClone]() {
195  // NOTE - this method uses shared_from_this to keep the engine alive
196  return geometrizerEngineClone->makeEnergyFunction();
197  }();
198 
199  emit q->signal_step(imageRunnerOptions, shapeCreator, energyFunction, addShapePreconditionFunction);
200  }
Here is the call graph for this function:

Member Data Documentation

◆ m_displayName

const std::string geometrize::task::ImageTask::ImageTaskImpl::m_displayName
private

Runtime configuration parameters for the runner.

◆ m_geometrizer

geometrize::script::GeometrizerEngine geometrize::task::ImageTask::ImageTaskImpl::m_geometrizer
private

The image task worker.

◆ m_id

const std::size_t geometrize::task::ImageTask::ImageTaskImpl::m_id
private

The display name of the image task.

◆ m_preferences

preferences::ImageTaskPreferences geometrize::task::ImageTask::ImageTaskImpl::m_preferences
private

◆ m_worker

ImageTaskWorker geometrize::task::ImageTask::ImageTaskImpl::m_worker
private

Thread that the image task worker runs on.

◆ m_workerThread

QThread geometrize::task::ImageTask::ImageTaskImpl::m_workerThread
private

A unique id for the image task.

◆ q

ImageTask* geometrize::task::ImageTask::ImageTaskImpl::q
private

The documentation for this class was generated from the following file:
geometrize::task::ImageTaskWorker::signal_willStep
void signal_willStep()
geometrize::task::ImageTask::signal_modelWillStep
void signal_modelWillStep()
signal_modelWillStep Signal that is emitted immediately before the underlying image task model is ste...
geometrize::preferences::ImageTaskPreferences::isScriptModeEnabled
bool isScriptModeEnabled() const
Definition: imagetaskpreferences.cpp:320
geometrize::task::ImageTaskWorker::drawShape
void drawShape(std::shared_ptr< geometrize::Shape > shape, geometrize::rgba color)
drawShape Draws a shape with the given color to the image task. Emits the willStep signal when called...
Definition: imagetaskworker.cpp:40
geometrize::task::ImageTask::ImageTaskImpl::m_id
const std::size_t m_id
The display name of the image task.
Definition: imagetask.cpp:292
geometrize::script::GeometrizerEngine::getEngine
chaiscript::ChaiScript * getEngine()
getEngine Gets a pointer to the script engine used by the shape mutation engine.
Definition: geometrizerengine.cpp:52
geometrize::task::ImageTask::ImageTaskImpl::q
ImageTask * q
Definition: imagetask.cpp:289
geometrize::task::ImageTask::ImageTaskImpl::init
void init(const Qt::ConnectionType connectionType)
Definition: imagetask.cpp:245
geometrize::preferences::ImageTaskPreferences::getScripts
std::map< std::string, std::string > getScripts() const
Definition: imagetaskpreferences.cpp:335
geometrize::task::ImageTask::ImageTaskImpl::getTarget
Bitmap & getTarget()
Definition: imagetask.cpp:67
geometrize::task::ImageTaskWorker::getCurrent
geometrize::Bitmap & getCurrent()
getCurrent Gets the current working bitmap.
Definition: imagetaskworker.cpp:49
geometrize::preferences::ImageTaskPreferences::getImageRunnerOptions
geometrize::ImageRunnerOptions getImageRunnerOptions() const
getImageRunnerOptions Gets a copy of the image runner options.
Definition: imagetaskpreferences.cpp:235
geometrize::task::ImageTask::ImageTaskImpl::disconnectAll
void disconnectAll()
Definition: imagetask.cpp:281
geometrize::task::ImageTask::modelDidStep
void modelDidStep(std::vector< geometrize::ShapeResult > shapes)
Definition: imagetask.cpp:387
geometrize::task::ImageTaskWorker::getTarget
geometrize::Bitmap & getTarget()
getTarget Gets the current target bitmap.
Definition: imagetaskworker.cpp:54
geometrize::task::ImageTask::ImageTaskImpl::m_workerThread
QThread m_workerThread
A unique id for the image task.
Definition: imagetask.cpp:293
geometrize::task::ImageTaskWorker::isStepping
bool isStepping() const
isStepping Returns true if the internal model is currently stepping.
Definition: imagetaskworker.cpp:74
geometrize::task::ImageTaskWorker::step
void step(geometrize::ImageRunnerOptions options, std::function< std::shared_ptr< geometrize::Shape >()> shapeCreator, geometrize::core::EnergyFunction energyFunction=nullptr, geometrize::ShapeAcceptancePreconditionFunction addShapePreconditionFunction=nullptr)
step Steps the image task worker. Emits the willStep signal when called, and didStep signal on comple...
Definition: imagetaskworker.cpp:28
geometrize::task::ImageTask::ImageTaskImpl::connectSignals
void connectSignals(const Qt::ConnectionType connectionType)
Definition: imagetask.cpp:273
geometrize::task::ImageTask::signal_step
void signal_step(geometrize::ImageRunnerOptions options, std::function< std::shared_ptr< geometrize::Shape >()> shapeCreator, geometrize::core::EnergyFunction energyFunction, geometrize::ShapeAcceptancePreconditionFunction addShapePrecondition)
signal_step Signal that the image task emits to make the internal model step.
geometrize::task::ImageTask::ImageTaskImpl::m_displayName
const std::string m_displayName
Runtime configuration parameters for the runner.
Definition: imagetask.cpp:291
geometrize::task::ImageTaskWorker::signal_didStep
void signal_didStep(std::vector< geometrize::ShapeResult > shapes)
geometrize::task::ImageTask::ImageTaskImpl::m_preferences
preferences::ImageTaskPreferences m_preferences
Definition: imagetask.cpp:290
geometrize::script::GeometrizerEngine::installScripts
void installScripts(const std::map< std::string, std::string > &scripts)
Definition: geometrizerengine.cpp:57
geometrize::task::ImageTask::ImageTaskImpl::m_worker
ImageTaskWorker m_worker
Thread that the image task worker runs on.
Definition: imagetask.cpp:294
geometrize::task::ImageTask::ImageTaskImpl::m_geometrizer
geometrize::script::GeometrizerEngine m_geometrizer
The image task worker.
Definition: imagetask.cpp:295
geometrize::task::ImageTask::signal_modelDidStep
void signal_modelDidStep(std::vector< geometrize::ShapeResult > shapes)
signal_modelDidStep Signal that is emitted immediately after the underlying image task model is stepp...
geometrize::task::ImageTask::modelWillStep
void modelWillStep()
Definition: imagetask.cpp:382
geometrize::task::ImageTask::signal_preferencesSet
void signal_preferencesSet()
signal_preferencesSet Signal that is emitted immediately after the image task preferences are set.
geometrize::task::ImageTask::signal_drawShape
void signal_drawShape(std::shared_ptr< geometrize::Shape > shape, geometrize::rgba color)
signal_drawShape Signal that the image task emits to draw a shape to the internal model.
geometrize::task::ImageTask::ImageTaskImpl::getId
static std::size_t getId()
Definition: imagetask.cpp:239