Adding objects in a batch

Discussion forum for C++ and script developers who are using the QCAD development platform or who are looking to contribute to QCAD (translations, documentation, etc).

Moderator: andrew

Forum rules

Always indicate your operating system and QCAD version.

Attach drawing files, scripts and screenshots.

Post one question per topic.

Post Reply
User avatar
hungerburg
Premier Member
Posts: 160
Joined: Fri May 28, 2010 7:35 pm

Adding objects in a batch

Post by hungerburg » Mon Feb 06, 2012 4:03 pm

In my scripts I add objects one primitive by one primitive. They execute quite fast. Still I want to ask:

For performance reasons, can one join several RAddObject Operations into one RAddObjects Operation? When I switch layers inbetween those, will the entities end up in the right ones then? Or does qcad optimze already?

User avatar
andrew
Site Admin
Posts: 9037
Joined: Fri Mar 30, 2007 6:07 am

Post by andrew » Sun Feb 12, 2012 8:54 pm

Yes, you can add multiple objects in one transaction. Setting the current to a different takes effect immediately and is not part of the transaction (i.e. changing the current layer cannot be undone).

User avatar
hungerburg
Premier Member
Posts: 160
Joined: Fri May 28, 2010 7:35 pm

Post by hungerburg » Tue Feb 14, 2012 4:59 pm

Seems I am a little confused by RAddObjectsOperation and RAddObjectOperation. In fact I only use the first plural one and never the second singular one.

These operations I call from helper functions, that draw geometric primitives, that create both operation and objects internally only.

Code: Select all

	var operation = new RAddObjectsOperation(false);
	var linie = new RLineData(linien[l][0], linien[l][1]);
	var entity = new RLineEntity(zeichnung.document, linie);
	operation.addObject(entity);
	zeichnung.documentInterface.applyOperation(operation);
If instead I kept on adding objects to the operation, and applied it only later, then would all objects end up in the same layer? Or in the layer, that was active, at the time they were added to the operation? Could it be about useCurrentAttributes?

I know it is trivial to find out myself, but I am lazy right now, please excuse the many words too, but maybe its interesting for others too. It may prove a performance benefit, especially when the script runs in the GUI.

User avatar
andrew
Site Admin
Posts: 9037
Joined: Fri Mar 30, 2007 6:07 am

Post by andrew » Tue Feb 14, 2012 8:41 pm

hungerburg wrote:If instead I kept on adding objects to the operation, and applied it only later, then would all objects end up in the same layer? Or in the layer, that was active, at the time they were added to the operation? Could it be about useCurrentAttributes?
To the layer that was the current layer when the object was added if 'useCurrentAttributes' is true (default) or to the layer explicitly set on the entity (setLayer(...)) if 'useCurrentAttributes' is false.

User avatar
hungerburg
Premier Member
Posts: 160
Joined: Fri May 28, 2010 7:35 pm

Post by hungerburg » Wed Feb 15, 2012 5:11 pm

Thank You Andrew, with this information I started to refactor. I nearly gave in, as everything would end up in the same layer. But now it works :)

Code: Select all

var operation = new RAddObjectsOperation(false); // not undo-able
document.setCurrentLayer("A");
// […] create some entity
operation.addObject(entity, false); // stick it to current layer
document.setCurrentLayer("B");
// […] add some more objects to the operation
operation.addObject(entity, false); // stick it to current layer
// […] add some more objects to the operation
documentInterface.applyOperation(operation);
The useCurrentAttributes flag works like this:
  • false: use attributes current at the time of the "add"
    true: use attributes current at the time of the "apply"
The performance gain is not noticeable though in command line mode or in linux GUI. I will see in windows GUI, because that is a little sluggish, when running scripts, compared to the linux one. Maybe that is only the grafics card though…

smf
Premier Member
Posts: 177
Joined: Tue Feb 28, 2012 1:05 pm

Re: Adding objects in a batch

Post by smf » Thu Jan 15, 2015 11:20 am

Hi Andrew,

this is an old thread, I know... But I think, my question belongs to it.

I'm trying to insert (copies of) several (sub-)entities. So I tried:

Code: Select all

    for (var j = 0; j < subIds.length; j++) {
      var sub = document.queryEntity(subIds[j]);
      var clone = sub.clone();
      clone.move(this.pos);
      //no changes with: storage.setObjectId(clone, RObject.INVALID_ID);
      //no changes with: clone.setLayerId(sub.getLayerId());
      op.addObject(clone, false); //nothing is ever inserted
      //this is working but entity is on wrong layer with: op.addObject(clone, true); 
    }
Insertion with useCurrentAttributes==true works, but is not what is wanted. Insertion with useCurrentAttributes==false does not insert anything. I tried to use setObjectId(...INVALID) and to set LayerId manually, but that does not change anything. What am I doing wrong?

Thanks in advance :)

User avatar
andrew
Site Admin
Posts: 9037
Joined: Fri Mar 30, 2007 6:07 am

Re: Adding objects in a batch

Post by andrew » Thu Jan 15, 2015 11:50 am

Can you pst a bit more code (what operation are you using, how do you apply the operation), thanks.

smf
Premier Member
Posts: 177
Joined: Tue Feb 28, 2012 1:05 pm

Re: Adding objects in a batch

Post by smf » Thu Jan 15, 2015 11:58 am

Thanks for the fast reaction. :) I have a script that has a block-id in this.blockId. The complete getOperation function is
InsertExplodedBlock.prototype.getOperation = function(preview) {
    var document = this.getDocument();
    if (isNull(document)) {
      return undefined;
    }
    var storage = document.getStorage(); //needed only for inserted "storage.setObjectId(clone, RObject.INVALID_ID);"

    var op = new RAddObjectsOperation();
    var block = document.queryBlock(this.blockId);
    if (isNull(block)) {
      EAction.handleUserMessage("internal error");
      this.setState(-1);
      this.terminate();
      return;
    }
    var subIds = document.queryBlockEntities(this.blockId);
    for (var j = 0; j < subIds.length; j++) {
      var sub = document.queryEntity(subIds[j]);
      var clone = sub.clone();
      clone.move(this.pos);
      op.addObject(clone, false);
    }

    return op;
};

The getOperation is called "as usual" by pickCoordinate:
InsertExplodedBlock.prototype.pickCoordinate = function(event, preview) {
    var di = this.getDocumentInterface();
    var document = this.getDocument();
    this.pos = event.getModelPosition();
    var op;

    switch (this.state) {
    case InsertExplodedBlock.State.SettingDestination:
      if (preview) {
        this.updatePreview();
      }
      else {
        op = this.getOperation(false);
        if (op == undefined) {
          break;
        }
        di.applyOperation(op);
        di.setRelativeZero(this.pos);
        this.setState(-1);
        this.terminate();
      }
      break;
    }
};

User avatar
andrew
Site Admin
Posts: 9037
Joined: Fri Mar 30, 2007 6:07 am

Re: Adding objects in a batch

Post by andrew » Thu Jan 15, 2015 2:00 pm

op.addObject(obj, false) inserts the object onto the same layer, into the same block as the original. If I understand the intention correctly, you want to insert the clone into the current block instead (?).
In this case, set the blockId of the clone to the current blockId and use op.addObject(obj, true) instead.

smf
Premier Member
Posts: 177
Joined: Tue Feb 28, 2012 1:05 pm

Re: Adding objects in a batch

Post by smf » Thu Jan 15, 2015 3:21 pm

andrew wrote:into the same block as the original
and
andrew wrote:you want to insert the clone into the current block instead
Yes, that's the point. I want to insert all entities onto the original layer but the current block.
andrew wrote:set the blockId of the clone to the current blockId and use op.addObject(obj, true) instead.
Thank you very much, this was it. With addO..true it didn't worked, but with addO..false. :D Now the code is:

Code: Select all

    var currentBlockId = document.getCurrentBlockId();
    var op = new RAddObjectsOperation();
    var subIds = document.queryBlockEntities(this.blockId);
    if (isNull(subIds)) {
      EAction.handleUserMessage("internal error");
      this.setState(-1);
      this.terminate();
      return;
    }
    for (var j = 0; j < subIds.length; j++) {
      var sub = document.queryEntity(subIds[j]);
      var clone = sub.clone();
      clone.setBlockId(currentBlockId);
      clone.move(this.pos);
      op.addObject(clone, false);
    }
Thanks again for the perfect support! :D

smf
Premier Member
Posts: 177
Joined: Tue Feb 28, 2012 1:05 pm

Re: Adding objects in a batch

Post by smf » Sun Jan 18, 2015 10:33 am

...with the code above, the original entities are removed from the original block. After inserting "storage.setObjectId(clone, RObject.INVALID_ID)" it works as desired. :)

Post Reply

Return to “QCAD Programming, Script Programming and Contributing”