A QisMLib extension to synthesize new layer from an expression of boolean operations between existing layers
QisMLayerSynth ExtensionLAYER SYNTHESIS SPEC.DEFAULT SPECPOSTFIX SPEC (compact and efficient)QisMLayerSynth C++ API (qismlayersynth.h)LSynthNotifyVersion Control (LSynthNotify)Begin_synthSynthesized_polygonInfo_messageWarning_messageEnd_synthLSynthNotifyV2Terminate_synthesisLSynthSpecObject_name (LSynthSpec)Version Control (LSynthSpec)Set_view_cellGet_view_cellSet_layer_specGet_layer_specSet_clipGet_clipSet_view_windowGet_view_window_llxGet_view_window_llyGet_view_window_urxGet_view_window_urySet_butting_modeGet_butting_modeGet_butting_overlapSet_remove_partitionsGet_remove_partitionsQisMLayerSynthObjectObject_name (QisMLayerSynthObject)Version Control (QisMLayerSynthObject)Get_last_error_msg (Get_last_error_msg)Get_last_error_code (Get_last_error_code)New_specDelete_specSynthesize_layersQisMLayerSynthObjectV2Synthesize_layers_advQisMLayerSynthVersion Control (QisMLayerSynth)Get_last_error_msg (QisMLayerSynth)Get_last_error_code (QisMLayerSynth)New_synthesizerDelete_synthesizerIs_layerspec_validQisMLayerSynth commandslsynth.new_synthesizerlsynth.delete_synthesizerlsynth.synthesize_layerslsynth.delete_storeQisMLayerSynth Licensing (API)QisMLayerSynth Licensing (Script)QisMLayerSynth Version Historyqismlayersynth dll/so v2.7 06-2020qismlayersynth dll/so v2.6 08-2019qismlayersynth dll/so v2.5 06-2018qismlayersynth dll/so v2.4 02-2018qismlayersynth dll/so v2.3 11-2017qismlayersynth dll/so v2.1 08-2017qismlayersynth dll/so v2.0 07-2017qismlayersynth dll/so v1.0 03-2017
x<layersynth-spec> := <target>[;<target>]* (One or more targets)<target> := <target-layer>:<target-dttp>=<op-layer>[:<op-dttp>] [<op><op-layer>[:<op-dttp>]]*(Generate a layer:dttp from operations on one or more layers or layer:dttps)<op> := '+' (union) or '-' (difference) or '&' (intersection) or '^' (xor) or',' (aggregation/OR-without-union) or '|' (aggregation/OR-without-union)
All <target-layer>:<target-dttp> will be outputted
Any hierarchy if present in the input is flattened
Examples:
100:0=2,5:0,7 (aggregate polygons on 2:* 5:0 and 7:* into a new layer 100:0)
100:0=2+5:0+7 (unionize polygons on 2:* 5:0 and 7:* into a new layer 100:0)
100:0=2+5:0-7 (unionize polygons on 2:* 5:0 and then subtract 7:* to create a new layer 100:0)
100:0=2,5:0-7 (aggregate polygons on 2:* 5:0 and then subtract 7:* to create a new layer 100:0)
100:0=2^5 (Compute XOR between 2:* and 5:* as 100:0)
100:0=2&5 (Compute INTERSECTION between 2:* and 5:* as 100:0)
100:0=2+5;200:0=100:0-5;300:0=200^5;400:0=300&5 (Create multiple synthesized layers from multiple operations between layers)
xxxxxxxxxx<layersynth-spec> := @<target>[<target>]*<target> := <operations><result><operations> := list of postfix operations resulting in ONE output. E.g:"L" (single layer all datatypes (A:*)) (0 <= L < 65535)"L:D" (single layer:datatype) (0 <= L,D < 65535)"A B +" (UNIONIZE A and B) (A,B can be of type L or L:D)"A B -" (SUBTRACT B from A)"A A ^" (XOR of A and B)"A B &" (INTERSECTION of A and B)"A B |" (Combine A and B without union)"A C =" (Assing A to C where C is of type L:D)"A B - C D & +" (same as (A - B) + (C & D))"A B - C & D +" (same as ((A - B) & C) + D)+ Not allowed:"A B - C D &" (because it results in TWO outputs A - B and C & D)<result> := Can be one of the following"R ~" (Emit the result as a new layer R where R is of type L:D, 0 <= L,D < 65535)"R *" (Unionize the result and emit it as a new layer R)
Example:
"@1 2:2 - 3:3 4 | & 0:0 ~"
First subtract 2:2 from 1:* (save the result to A)
Then, combine 3:3 and 4:* (save the result to B)
Intersect A and B (save the result to C)
Output C as 0:0
"@1 2 ^ 100:0 = 0:0 ~ 3 4 | 200:0 = 0:1 * 100:0 200:0 & 0:3 ~"
First xor 1:* and 2:* and save the result to 100:0
Next, emit the result as 0:0
New expression, combine 4:* and 3:* and save that as 200:0
Next, unionize the result and emit as 0:1
Finally, intersect 100:0 with 200:0 and emit the result as 0:3
API for the QismLayerSynth notifications handler (callback client)
xxxxxxxxxxclass LSynthNotify { ... };Cast a pointer to your handler to any type in the LSynthNotify hierarchy using the version number.
The version of a class is embedded in the name in form of a suffix V
The version of the topmost base class is 1. E.g if LSynthNotify is the topmost base class (version 1), LSynthNotifyV2 LSynthNotifyV3 etc. would be the future extensions of LSynthNotify.
Return NULL if the version number is not recognized/implemented
xxxxxxxxxxvirtual void* LSynthNotify_cast(const int version) = 0;/* PLEASE ADD THE FOLLOWING IMPLEMENTATION IN YOUR HANDLER { switch(version) { case 0: return this; case 1: return dynamic_cast<LSynthNotify*>(this); //Add more casts based on the implementation of your handler } return 0;} */virtual const void* LSynthNotify_cast(const int version) const = 0;/* PLEASE ADD THE FOLLOWING IMPLEMENTATION IN YOUR HANDLER { switch(version) { case 0: return this; case 1: return dynamic_cast<const LSynthNotify*>(this); //Add more casts based on the implementation of your handler } return 0;} */virtual int LSynthNotify_latest_version() const = 0;/* PLEASE ADD THE FOLLOWING IMPLEMENTATION IN YOUR HANDLER { return 1; //Return the newest version implemented by your handler } */Notification at the start of the synthesis of a new layer
layer: Layer number of the synthesized layer (target)
dttp: Datatype number of the synthesized layer (target)
Return true if the client wants to recieve the polygons created on this layer via the Synthesized_polygon notification
xxxxxxxxxxvirtual bool Begin_synth(const int layer, const int dttp) { return true; }Notification to recieve a single synthesized polygon
xy: XY-coordines of the synthesized polygon (database units)
numXY: No. xy pairs in xy (e.g 5 for a rectangle)
grid: Size of a single database unit in file units (e.g 0.001 for a micron file with nanometer resolution)
layer: Layer number of the synthesized layer
dttp: Datatype number of the synthesized layer
The address of the xy coordinates is valid only during this callback. Make a copy of the entire array in order to use these coordinates later
xxxxxxxxxxvirtual int Synthesized_polygon( const int* xy, const int numXY, const double grid, const int layer, const int dttp ) { return 0; }Notifying any information related to the layer synthesis
pre, post: Prefix and suffix for formatting the message
msg: Information string
xxxxxxxxxxvirtual int Info_message( const char* pre, const char* msg, const char* post ) { return 0; }Notifying any warnings related to the layer synthesis
pre, post: Prefix and suffix for formatting the message
msg: Warning string
xxxxxxxxxxvirtual int Warning_message( const char* pre, const char* msg, const char* post ) { return 0; }Notification at the end of the synthesis of a new layer
layer: Layer number of the synthesized layer (target)
dttp: Datatype number of the synthesized layer (target)
xxxxxxxxxxvirtual void End_synth(const int layer, const int dttp) { }Handlers of this class MUST define LSynthNotify_cast, LSynthNotify_cast const and LSynthNotify_latest_version correctly for version = 2
xxxxxxxxxxclass LSynthNotifyV2: public LSynthNotify { ... };Return non-zero value to terminate the layer synthesis
This callback may be invoked from multiple independent threads
It's the client's responsibility to make sure shared data is protected appropriately
xxxxxxxxxxvirtual int Terminate_synthesis() { return 0; }Layer synthesis specification object
xxxxxxxxxxclass LSynthSpec { ... };Get implementation name and version
xxxxxxxxxxvirtual const char* Object_name() const = 0;Cast to a pointer of another version in the class hierarchy (base/derived).
Get the latest version number
Version numbers start at 1 and are reflected in the class name using the suffix V
The topmost base class is version 1 (V1 implied)
The cast returns NULL if a version number is not recognized/implemented
xxxxxxxxxxvirtual void* LSynthSpec_cast(const int version) = 0;virtual const void* LSynthSpec_cast(const int version) const = 0;virtual int LSynthSpec_latest_version() const = 0;Set/Get the view cell
cellName: Name of a valid cell. Default: Deepest top cell
xxxxxxxxxxvirtual void Set_view_cell(const char* cellName) = 0;virtual const char* Get_view_cell() const = 0;Set/Get the layer synthesis specification (Required)
str: Layer specification string. Refere to 'LAYER SYNTHESIS SPEC' for syntax and details
xxxxxxxxxxvirtual void Set_layer_spec(const char* str) = 0;virtual const char* Get_layer_spec() const = 0;Set/Get clipping ON/OFF. Default: OFF
xxxxxxxxxxvirtual void Set_clip(const bool set = true) = 0;virtual bool Get_clip() const = 0;Set/Get extraction/clipping window
llur: llur[0] = minX/llx, llur[1] = minY/lly, llur[2] = maxX/urx and llur[3] = maxY/ury of the window to be set
By default, the view cell's extents are used
xxxxxxxxxxvirtual void Set_view_window(const double llur[4]) = 0;virtual double Get_view_window_llx() const = 0;virtual double Get_view_window_lly() const = 0;virtual double Get_view_window_urx() const = 0;virtual double Get_view_window_ury() const = 0;Set/Get mode to represent output polygons with holes
set: If true, split polygons with holes as a collection of butting polygons otherwise, output polygons have cutlines joining the outer boundary with those of the holes
overlap: In butting mode, the amount of overlap between polygons along the butting edges. Default: 0.0 file units
xxxxxxxxxxvirtual void Set_butting_mode(const bool set, const double overlap) = 0;virtual bool Get_butting_mode() const = 0;virtual double Get_butting_overlap() const = 0;Set/Get mode to remove thread partition lines after the boolean operation is complete
Setting this (true) will result in cleaner data (less edges) by trading off compute speed (slower)
Default: true
xxxxxxxxxxvirtual void Set_remove_partitions(const bool set) = 0;virtual bool Get_remove_partitions() const = 0;An API to work with a single instance of the layer synthesizer object
xxxxxxxxxxclass QisMLayerSynthObject { ... };Get implementation name and version
xxxxxxxxxxvirtual const char* Object_name() const = 0;Cast to a pointer of another version in the class hierarchy (base/derived).
Get the latest version number
Version numbers start at 1 and are reflected in the class name using the suffix V
The topmost base class is version 1 (V1 implied)
The cast returns NULL if a version number is not recognized/implemented
xxxxxxxxxxvirtual void* QisMLayerSynthObject_cast(const int version) = 0;virtual const void* QisMLayerSynthObject_cast(const int version) const = 0;virtual int QisMLayerSynthObject_latest_version() const = 0;Get the error message and code corresponding to the last error condition
xxxxxxxxxxvirtual const char* Get_last_error_msg() const = 0;virtual int Get_last_error_code() const = 0;Create/Destroy a layer synthesis specification (settings) object
Every spec object created by New_spec must be destroyed using Delete_spec to avoid memory leak
xxxxxxxxxxvirtual LSynthSpec* New_spec() = 0;virtual void Delete_spec(LSynthSpec* handle) = 0;Synthesize one or more layers as per the layer synthesis specification
spec: Layer synthesis settings
client: Address of a notification handler (callback) to recieve synthesized polygons and other notifications
thrnum: Number of threads to be used for various boolean operations
Success: true
Failure: false. Call Get_last_error_msg or Get_last_error_code to get more information
Refer to 'LAYER SYNTHESIS SPEC' for layer synthesis specification syntax
This procedure emits a LSynthNotify::Begin_synth and LSynthNotify::End_synth notification for every newly synthesized/target layer with one or more LSynthNotify::Synthesized_polygon notifications in-between, for every polygon created for that layer
If the client returns false from LSynthNotify::Begin_synth, no Synthesized_polygon or End_synth notifications are sent for that layer
xxxxxxxxxxvirtual bool Synthesize_layers( const LSynthSpec* spec, LSynthNotify* client, const int thrnum ) = 0;Extension v2 to QisMLayerSynthObject with support for advanced control on the boolean operations by specifying the boolean settings object directly (qismbool.h)
xxxxxxxxxxclass QisMLayerSynthObjectV2: public QisMLayerSynthObject { ... };Works just like
Synthesize_layersexcept:
The specified opts are used to control results of boolean ops
This is an advanced feature. It's assumed that the client is aware of the implications of the various QisMBoolSettingsV2 features
Various LSynthSpec features (butting, overlap, merge partitions) will override the corresponding QisMBoolSettingsV2 features
xxxxxxxxxxvirtual bool Synthesize_layers_adv( const LSynthSpec* spec, LSynthNotify* client, const NsQisMLib::QisMBoolSettingsV2* opts, const int thrnum ) = 0;API to synthesize/create new layers of polygons by performing a sequence of boolean operations between layers
xxxxxxxxxxclass QisMLayerSynth: public NsQisMLib::QisMExtensionAPI { ... };Cast to a pointer of another version in the class hierarchy (base/derived).
Get the latest version number
Version numbers start at 1 and are reflected in the class name using the suffix V
The topmost base class is version 1 (V1 implied)
The cast returns NULL if a version number is not recognized/implemented
xxxxxxxxxxvirtual void* QisMLayerSynth_cast(const int version) = 0;virtual const void* QisMLayerSynth_cast(const int version) const = 0;virtual int QisMLayerSynth_latest_version() const = 0;Get the error message and code corresponding to the last error condition
xxxxxxxxxxvirtual const char* Get_last_error_msg() const = 0;virtual int Get_last_error_code() const = 0;Create/Destroy a new instance of the layer synthesis object
Success: A non-null handle to a new layer synthesis object
Failure: NULL. Call Get_last_error_msg or Get_last_error_code to get more information
filedb: Handle to a valid QisMFile database
argC, argT, argV: reserved
handle: Handle to a valid layer synthesis object to destroy
All layer synthesis object MUST be created and destroyed in the main thread
Upon creation however, individual objects may be used in different threads for different synthesis jobs
A single QISMCODE_QISMLSYNTH license is required per active object
xxxxxxxxxxvirtual QisMLayerSynthObject* New_synthesizer( NsQisMLib::QisMFile* filedb, const int argC = 0, const char* const* argT = 0, void* const* argV = 0 ) = 0;virtual void Delete_synthesizer(QisMLayerSynthObject* handle) = 0;Check if a layer synthesis specification is syntactically correct
layerspec: Layer synthesis string
Success: true
Failure: false. Call Get_last_error_msg or Get_last_error_code for syntax error information
xxxxxxxxxxvirtual bool Is_layerspec_valid(const char* layerspec) const = 0;Requires the QisMLayerSynth extension to be installed and loaded (qismlayersynth64.dll/so)
Select commands may require a valid license
See qismlayersynth.h for the corresponding API
xxxxxxxxxxlsynth.new_synthesizer&lsynth={lsynth_id}$filedb={filedb_id}
Create a new layer synthesizer object
Equivalent to QisMLayerSynth::New_synthesizer in qismlayersynth.h
Requires 1 license of (11069) which will be release during lsynth.delete_synthesizer
{lsynth_id} represents name of a variable of type QisMLayerSynthObject* associated with the object to be created
{filedb_id} represents name of a variable of type QisMFile* associated with the file database linked with the synthesizer
Every object created using this command MUST be eventually destroyed using lsynth.delete_synthesizer to avoid resource leaks
xxxxxxxxxxlsynth.delete_synthesizer$lsynth={lsynth_id}
Destroy a layer synthesizer object
Releases 1 license of (11069) acquired during lsynth.new_synthesizer
{lsynth_id} represents name of a variable of type QisMLayerSynthObject* associated with the object to be destroyed
xxxxxxxxxxlsynth.synthesize_layers$lsynth={lsynth_id}&bin={bin_id}spec={lsynth_spec}[cell={cellname}][clip][window={minx},{miny},{maxx},{maxy}][butting={overlap}][nostripes][thrnum={n_threads}]
Synthesize layers based on an expression
Equivalent to QisMLayerSynthObject::Synthesize_layers in qismlayersynth.h
{lsynth_id} represents name of a variable of type QisMLayerSynthObject* associated with the synthesizer object
{bin_id} represents name of a variable of type QisMBStore* associated with the set of boundaries to be created to store the synthesized polygons
{lsynth_spec} is the layer synthesis expression
{cellname} if used indicates the view cell. Default -- default top cell
clip is used causes the output to be clipped to the specified window. Default -- no clipping
{minx}..{maxy} if used represents a window of interest with min/max extents in file units. Default -- extents of the view cell
butting if used causes output polygons with holes to be broken up into butting polygons (along X) with the specified {overlap} value. Default -- Polygons with holes have cutlines
nostripes if used, causes partitioning lines in the output to be merged. Default -- off
{n_threads} if used indicates the number of threads to be used for performing boolean operations. Default -- 0 (automatic based on no. cpus in the system)
The newly created {bin_id} MUST be eventually destroyed using lsynth.delete_store to avoid resource leaks
xxxxxxxxxxlsynth.delete_store$bin={bin_id}
Delete a container of boundaries created only by lsynth.synthesize_layers
{bin_id} represents name of a variable of type QisMBStore* associated with the container to be destroyed
Product name:
QisMLayerSynthLicense code:11069
The following operations require ONE license of QisMLayerSynth, acquired during BEGIN and released during END
Product name:
QisMLayerSynthLicense code:11069
The following operations require ONE license of QisMLayerSynth, acquired during BEGIN and released during END
misc. bug fixes & memory leaks
New API QisMLayerSynthObjectV2 to facilitate advanced control of the results by specifying the QisMBoolSettingsV2 object
Support for scripting via QisMScript
Compatible with QisMLib 3.20 (API break)
This extension will not load with earlier versions of QisMLib
New LSynthNotify extension to check with the client if the layer synthesis is to be terminated
Compatible with QisMLib v3.9 (API break)
New feature LSynthSpec::Remove_partitions to remove thread partitions or not after boolean operations
Bug fix: Rounding error during conversion of double to int
Support for a new post-fix layer synthesis expressions which is both compact and more efficient. This should be the best way to use layer synthesizer
First cut
Last Updated -- Sun Apr 6 19:26:14 UTC 2025