Page 1 of 1

Adding objects in a batch

Posted: Mon Feb 06, 2012 4:03 pm
by hungerburg
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?

Posted: Sun Feb 12, 2012 8:54 pm
by andrew
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).

Posted: Tue Feb 14, 2012 4:59 pm
by hungerburg
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.

Posted: Tue Feb 14, 2012 8:41 pm
by andrew
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.

Posted: Wed Feb 15, 2012 5:11 pm
by hungerburg
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…

Re: Adding objects in a batch

Posted: Thu Jan 15, 2015 11:20 am
by smf
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 :)

Re: Adding objects in a batch

Posted: Thu Jan 15, 2015 11:50 am
by andrew
Can you pst a bit more code (what operation are you using, how do you apply the operation), thanks.

Re: Adding objects in a batch

Posted: Thu Jan 15, 2015 11:58 am
by smf
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;
    }
};

Re: Adding objects in a batch

Posted: Thu Jan 15, 2015 2:00 pm
by andrew
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.

Re: Adding objects in a batch

Posted: Thu Jan 15, 2015 3:21 pm
by smf
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

Re: Adding objects in a batch

Posted: Sun Jan 18, 2015 10:33 am
by smf
...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. :)