/** * Copyright (c) 2011-2018 by Andrew Mustun. All rights reserved. * * This file is part of the QCAD project. * * QCAD is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * QCAD is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with QCAD. */ // CVH kept IOExamples.js as in ExDumpPolyline.js include("../IOExamples.js"); // CVH added sprintf.js from GitHub in subdir C:\Program Files\QCAD\scripts // CVH added include sprintf.js here: It is not included by library.js include("scripts/sprintf.js"); // Script was NOT present // CVH added include File.js as in BlockListExport.js include("scripts/File/File.js"); // Script is NOT present /** * \ingroup ecma_misc_examples_ioexamples * \class DocBasicEntities * This action documents all selected basic entities as plain text into the * command line history and/or a CSV file. */ function DocBasicEntities(guiAction) { IOExamples.call(this, guiAction); } DocBasicEntities.prototype = new IOExamples(); DocBasicEntities.prototype.beginEvent = function() { IOExamples.prototype.beginEvent.call(this); // CVH added export to CSV file as in BlockListExport.js // Added the .getFileName function below // Added the next two tests, the ts.writeString entries and the file.close() entry debugger; // To pause and open the debugger window var di = this.getDocumentInterface(); // DO NOT understand setting of di // variable was originally not used here. var document = this.getDocument(); var ids = document.querySelectedEntities(); // Qlist with selected var idCount = ids.length; // Number of selected var idn = idCount; // Number to process var idp = 0; // Counter processed var firstOtype = true; // Flag, use type header if true var msg = "", nominator = ""; // Message strings var dmpCom = idn <= 3; // Flag, dump to command history when idn<=3 or no open file var csvExp = false; // Flag, CSV export when idn>3 and open file var posRv , startRv , endRv , aux1Rv; // Intermediate Rvectors storage var i , id , entity; // Loop variables EAction.handleUserCommand("IOExamples: Document Basic Entities"); if (idn == 0) { // Terminate without entities selected EAction.handleUserWarning("No entities selected!"); this.terminate(); return; } var fileName = this.getFileName(); // .getFileName as in BlockListExport.js if (isNull(fileName)) { // Without a filename > dmpCom = true; // Force command dump } else { // With a filename var file = new QFile(fileName); var flags = new QIODevice.OpenMode(QIODevice.WriteOnly | QIODevice.Text); if (!file.open(flags)) { // Without open file > dmpCom = true; // Force command dump EAction.handleUserWarning("No file opened!"); } else { // With open file > csvExp = true // CSV export } } if (dmpCom) {EAction.handleUserInfo("Basic Entities Dump");} if (csvExp) { var ts = new QTextStream(file); ts.writeString("Basic Entities Dump"); ts.writeString("\nSelected Entities: "+ idCount); ts.writeString("\n+++++ +++++++ +++++"); } // CVH added point entity types for (i=idn-1; i>=0; i--) { // Cycle through all selected // Backwards wat is conveniently for Qlist splicing id = ids[i]; entity = document.queryEntity(id); if (isPointEntity(entity)) { if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Point dump:");} if (csvExp) {ts.writeString("\n\nPoint dump:\nNominator; Layer; Position x; y;");} firstOtype = false; } posRv = entity.getPosition(); if (dmpCom) { // More verbose on command history EAction.handleUserMessage("Pnt;%1;%2;" .arg(numberToString(posRv.x, 4)) .arg(numberToString(posRv.y, 4))); } if (csvExp) { // Full Reproduceable data ts.writeString("\nPnt;%1;%2;%3;" .arg(entity.getLayerName()) .arg(numberToString(posRv.x, 10)) .arg(numberToString(posRv.y, 10))); } idp++; // Increase processed counter // We don't want to reprocess this entity for other types ids.splice(i,1); // Remove entity from Qlist idn--; // Decrease number to process // One could deselect the entity at these points // This will not affect the Qlist ids with the originally selected // di.deselectEntity(id); // Needs var di = this.getDocumentInterface() } } firstOtype = true; // CVH added line entity types for (i=idn-1; i>=0; i--) { // Cycle through all remaining id = ids[i]; entity = document.queryEntity(id); if (isLineBasedEntity(entity)) { // Rays & Xlines are defined similar as simple lines if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Line dump:");} if (csvExp) {ts.writeString("\n\nLine dump:\nNominator; Layer; Start x; y; End x; y;");} firstOtype = false; } if (isRayEntity(entity)) { nominator = "Ray"; startRv = entity.getBasePoint(); endRv = entity.getSecondPoint(); } else if (isXLineEntity(entity)) { nominator = "Xlin"; startRv = entity.getBasePoint(); endRv = entity.getSecondPoint(); } else { nominator = "Line"; startRv = entity.getStartPoint(); endRv = entity.getEndPoint(); } if (dmpCom) { EAction.handleUserMessage("%1;%2;%3;%4;%5;" .arg(nominator) .arg(numberToString(startRv.x, 4)) .arg(numberToString(startRv.y, 4)) .arg(numberToString(endRv.x, 4)) .arg(numberToString(endRv.y, 4))); } if (csvExp) { ts.writeString("\n%1;%2;%3;%4;%5;%6;" .arg(nominator) .arg(entity.getLayerName()) .arg(numberToString(startRv.x, 10)) .arg(numberToString(startRv.y, 10)) .arg(numberToString(endRv.x, 10)) .arg(numberToString(endRv.y, 10))); } idp++; ids.splice(i,1); idn--; } } firstOtype = true; // CVH added arc entity types for (i=idn-1; i>=0; i--) { // Cycle through all remaining id = ids[i]; entity = document.queryEntity(id); if (isArcEntity(entity)) { if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Arc dump:");} if (csvExp) {ts.writeString("\n\nArc dump:\nNominator; Layer; Center x; y; Radius; Start-; End-Angle;");} firstOtype = false; } posRv = entity.getCenter(); nominator = entity.isReversed() ? "Arc" : "ArcR"; if (dmpCom) { EAction.handleUserMessage("%1;%2;%3;%4;%5;%6;" .arg(nominator) .arg(numberToString(posRv.x, 4)) .arg(numberToString(posRv.y, 4)) .arg(numberToString(entity.getRadius(), 4)) .arg(numberToString(entity.getStartAngle(), 4)) .arg(numberToString(entity.getEndAngle(), 4))); } // Radians! Multiply with Math.PI/2 for degrees if (csvExp) { ts.writeString("\n%1;%2;%3;%4;%5;%6;%7;" .arg(nominator) .arg(entity.getLayerName()) .arg(numberToString(posRv.x, 10)) .arg(numberToString(posRv.y, 10)) .arg(numberToString(entity.getRadius(), 10)) .arg(numberToString(entity.getStartAngle(), 10)) .arg(numberToString(entity.getEndAngle(), 10))); } idp++; ids.splice(i,1); idn--; } } firstOtype = true; // CVH added circle entity types for (i=idn-1; i>=0; i--) { // Cycle through all remaining id = ids[i]; entity = document.queryEntity(id); if (isCircleEntity(entity)) { if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Circle dump:");} if (csvExp) {ts.writeString("\n\nCircle dump:\nNominator; Layer; Center x; y; Radius;");} firstOtype = false; } posRv = entity.getCenter(); if (dmpCom) { EAction.handleUserMessage("Cir;%1;%2;%3;" .arg(numberToString(posRv.x, 4)) .arg(numberToString(posRv.y, 4)) .arg(numberToString(entity.getRadius(), 4))); } if (csvExp) { ts.writeString("\nCir;%1;%2;%3;%4;" .arg(entity.getLayerName()) .arg(numberToString(posRv.x, 10)) .arg(numberToString(posRv.y, 10)) .arg(numberToString(entity.getRadius(), 10))); } idp++; ids.splice(i,1); idn--; } } firstOtype = true; // CVH added ellipse entity types for (i=idn-1; i>=0; i--) { // Cycle through all remaining id = ids[i]; entity = document.queryEntity(id); if (isEllipseEntity(entity)) { if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Ellipse dump:");} if (csvExp) {ts.writeString("\n\nEllipse dump\nNominator; Layer; Center x; y; Major point x; y; Ratio; Start-; End-par.; Start-; End-Angle;");} firstOtype = false; } posRv = entity.getCenter(); aux1Rv = entity.getMajorPoint(); nominator = entity.isReversed() ? "Eli" : "EliR"; if (dmpCom) { EAction.handleUserMessage("%1;%2;%3;%4;%5;%6;%7;%8;%9;%10;" .arg(nominator) .arg(numberToString(posRv.x, 4)) .arg(numberToString(posRv.y, 4)) .arg(numberToString(aux1Rv.x, 4)) .arg(numberToString(aux1Rv.x, 4)) .arg(numberToString(entity.getRatio(), 4)) .arg(numberToString(entity.getStartParam(), 4)) .arg(numberToString(entity.getEndParam(), 4)) .arg(numberToString(entity.getStartAngle(), 4)) .arg(numberToString(entity.getEndAngle(), 4))); } // Radians! Multiply with Math.PI/2 for degrees if (csvExp) { ts.writeString("\n%1;%2;%3;%4;%5;%6;%7;%8;%9;%10;%11;" .arg(nominator) .arg(entity.getLayerName()) .arg(numberToString(posRv.x, 10)) .arg(numberToString(posRv.y, 10)) .arg(numberToString(aux1Rv.x, 10)) .arg(numberToString(aux1Rv.x, 10)) .arg(numberToString(entity.getRatio(), 10)) .arg(numberToString(entity.getStartParam(), 10)) .arg(numberToString(entity.getEndParam(), 10)) .arg(numberToString(entity.getStartAngle(), 10)) .arg(numberToString(entity.getEndAngle(), 10))); } idp++; ids.splice(i,1); idn--; } } firstOtype = true; // CVH added spline entity types // There are two built in Control points & Fit points // and at least one extra supported type (string of Béziers) // #TODO# How to dump/export splines // Maybe similar as polyline dump, a block each for (i=idn-1; i>=0; i--) { // Cycle through all remaining id = ids[i]; entity = document.queryEntity(id); if (isSplineEntity(entity)) { if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Spline entity:");} if (csvExp) {ts.writeString("\n\nSpline entity:\nNominator; Selection id; yyy; Layer;");} firstOtype = false; } var xxx = id; // Dummy's var yyy = id+0.22; var zzz = entity.getLayerName(); if (dmpCom) { EAction.handleUserMessage("Spl;%1;%2;%3;" .arg(numberToString(xxx, 4)) .arg(numberToString(yyy, 4)) .arg(zzz)); } if (csvExp) { ts.writeString("\nSpl;%1;%2;%3;" .arg(numberToString(xxx, 10)) .arg(numberToString(yyy, 10)) .arg(zzz)); } idp++; ids.splice(i,1); idn--; } } firstOtype = true; // Polyline entity types as in ExDumpPolyline.js for (i=idn-1; i>=0; i--) { // Cycle through all remaining id = ids[i]; // Pick list entry entity = document.queryEntity(id); // Pick entity if (isPolylineEntity(entity)) { //isLeaderEntity(entity) // = polyline with arrow var vn = entity.countVertices(); // Test for logi. closed, phys. closed or open polyline if (entity.isGeometricallyClosed()) { // The vertices are forming a Polygon msg = entity.isClosed() ? "Logi. Closed base Polygon" : "Phys. Closed base Polygon"; } else { msg = "Open Polyline"; } // CVH remarks orientation is for a closed form or (simple) polygon // For some types of open polylines it is not stricktly defined // Bulging may affect orientation if (DocBasicEntities.isClockwise(entity)) { // Function .isClockwise in this file msg = "Clockwise " + msg; } else { msg = "Counter Clockwise " + msg; } if (dmpCom) {EAction.handleUserMessage(msg);} if (csvExp) {ts.writeString("\n\n" + msg);} // CVH added reporting orientation as ExDumpPolyline recently does // This can be different in rare cases var ori = entity.getOrientation(true); if (ori===RS.CW) { msg = "QCAD reports CW"; } else if (ori===RS.CCW) { //RS::Orientation can be: UnknownOrientation; Any; CW; CCW msg = "QCAD reports CCW"; } // CVH added reporting arc segments if (1<0) { // not working var test1 = entity.bulges(); var test2 = entity.hasArcSegments(); } if (DocBasicEntities.hasArcSegments(entity)) { // Workaround function .hasArcSegments in this file msg = msg + "; Including arcs"; } else { msg = msg + "; Line segments"; } if (dmpCom) { EAction.handleUserMessage(msg); EAction.handleUserMessage(vn + " Vertices dump:"); } if (csvExp) { ts.writeString("\n" + msg); ts.writeString("\n" + vn + " Vertices dump:\nx; y; bulge;"); } for (var k=0; k=0; i--) { // Cycle through all remaining id = ids[i]; entity = document.queryEntity(id); if (isHatchEntity(entity)) { if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Hatch dump:");} if (csvExp) {ts.writeString("\n\nHatch dump:\nNominator; Layer; Selection id; Origin x; y;");} firstOtype = false; } posRv = entity.getOriginPoint(); // #TODO# Not the position if (dmpCom) { EAction.handleUserMessage("Hatch;%1;%2;%3;" .arg(id) // #TODO# Not relevant .arg(numberToString(posRv.x, 4)) .arg(numberToString(posRv.y, 4))); } if (csvExp) { ts.writeString("\nHatch;%1;%2;%3;%4;" .arg(entity.getLayerName()) .arg(id) .arg(numberToString(posRv.x, 10)) .arg(numberToString(posRv.y, 10))); } idp++; ids.splice(i,1); idn--; } } firstOtype = true; // CVH added text entity types for (i=idn-1; i>=0; i--) { // Cycle through all remaining id = ids[i]; entity = document.queryEntity(id); if (isTextEntity(entity)) { if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Text dump:");} if (csvExp) {ts.writeString("\n\nText dump:\nNominator; Layer; Position x; y; Font; Height; XScale; HAlign; VAlign; Angle; \"PlainText\";");} firstOtype = false; } posRv = entity.getAlignmentPoint(); // not allways the same as .getPosition() if (dmpCom) { EAction.handleUserMessage("Txt;%1;%2;%3;%4;%5;%6;%7;" .arg(numberToString(posRv.x, 4)) .arg(numberToString(posRv.y, 4)) .arg(entity.getFontName()) .arg(numberToString(entity.getHeight(), 4)) .arg(numberToString(entity.getXScale(), 4)) .arg(numberToString(entity.getAngle(), 4)) // PlainText may incl. linefeed > Text in quotation marks .arg("\"" + entity.getPlainText() + "\"")); } // Radians! Multiply with Math.PI/2 for degrees if (csvExp) { ts.writeString("\nTxt;%1;%2;%3;%4;%5;%6;%7;%8;%9;%10;" .arg(entity.getLayerName()) .arg(numberToString(posRv.x, 10)) .arg(numberToString(posRv.y, 10)) .arg(entity.getFontName()) .arg(numberToString(entity.getHeight(), 5)) .arg(numberToString(entity.getXScale(), 5)) .arg(entity.getHAlign()) .arg(entity.getVAlign()) .arg(numberToString(entity.getAngle(), 10)) .arg("\"" + entity.getPlainText() + "\"")); } idp++; ids.splice(i,1); idn--; } } firstOtype = true; // CVH added dimension entity types for (i=idn-1; i>=0; i--) { // Cycle through all remaining id = ids[i]; entity = document.queryEntity(id); if (isDimensionEntity(entity)) { if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Dimension dump:");} if (csvExp) {ts.writeString("\n\nDimension dump:\nNominator+id; Layer; TxtPos x; y; ExtPnt1 x; y; ExtPnt1 x; y; Text;");} firstOtype = false; } msg = (isDimAlignedEntity(entity) ? "DimLnAl" : "NaN") // Layer* ; Color ; LineW ; LineT ; AutoLabel ; Label ; Fistflip ; SecondFlip ; fixExt ; ExtensionLenght ; LinearFactor; Scale ; Tolerance ; TextPosition*; DimLine* ; ExtensionPoint1 ; ExtensionPoint2 msg = (isDimRotatedEntity(entity) ? "DimLnRo" : msg) // Layer* ; Color ; LineW ; LineT ; AutoLabel ; Label ; Fistflip ; SecondFlip ; fixExt ; ExtensionLenght ; LinearFactor; Scale ; Angle ; Tolerance ; TextPosition* ; Dimline* ;ExtensionPoint1 ; ExtensionPoint2 msg = (isDimOrdinateEntity(entity) ? "DimOrdi" : msg) // Layer* ; Color ; LineW ; LineT ; AutoLabel ; Label ; Fistflip ; SecondFlip ; fixExt ; ExtensionLenght ; LinearFactor; Scale ; Ordinate ; Tolerance ; TextPosition* ; OriginPoint ; DefPoint ; LeaderEndPoint msg = (isDimRadialEntity(entity) ? "DimRadi" : msg) // Layer* ; Color ; LineW ; LineT ; AutoLabel ; Label ; Fistflip ; SecondFlip ; fixExt ; ExtensionLenght ; LinearFactor; Scale ; Tolerance ; TextPosition* ; ChordPoint ; CenterPoint msg = (isDimDiametricEntity(entity) ? "DimDiam" : msg) // Layer* ; Color ; LineW ; LineT ; AutoLabel ; Label ; Fistflip ; SecondFlip ; fixExt ; ExtensionLenght ; LinearFactor; Scale ; Tolerance ; TextPosition* ; ChordPoint ; FarChordPoint msg = (isDimAngular2LEntity(entity) ? "DimA2Li" : msg) // Layer* ; Color ; LineW ; LineT ; AutoLabel ; Label ; Fistflip ; SecondFlip ; fixExt ; ExtensionLenght ; Scale ; Tolerance ; TextPosition* ; Line1Start ; Line1End ; Line2Start ; Line2End ; DimArc msg = (isDimAngular3PEntity(entity) ? "DimA3Pt" : msg) // Layer* ; Color ; LineW ; LineT ; AutoLabel ; Label ; Fistflip ; SecondFlip ; fixExt ; ExtensionLenght ; Scale ; Tolerance ; TextPosition* ; CenterPoint ; Line1End ; Line2End ; DimArc msg = (isDimArcLengthEntity(entity) ? "DimArcL" : msg) // Layer* ; Color ; LineW ; LineT ; AutoLabel ; Label ; Fistflip ; SecondFlip ; fixExt ; ExtensionLenght ; Scale ; ArcSymbolType ; Tolerance ; TextPosition* ; CenterPoint ; Line1End ; Line2End ; DimArc nominator = msg posRv = entity.getTextPosition(); startRv = entity.getDefinitionPoint(); // entity.getExtensionPoint1(); endRv = entity.getDefinitionPoint(); // entity.getExtensionPoint2(); aux1Rv = entity.getDefinitionPoint(); if (dmpCom) { EAction.handleUserMessage("%1;%2;%3;%4;%5;%6;%7;%8;%9;%10;" .arg(nominator + id) // #TODO# Not relevant .arg(numberToString(posRv.x, 4)) .arg(numberToString(posRv.y, 4)) .arg(numberToString(aux1Rv.x, 4)) .arg(numberToString(aux1Rv.y, 4)) .arg(numberToString(startRv.x, 4)) .arg(numberToString(startRv.y, 4)) .arg(numberToString(endRv.x, 4)) .arg(numberToString(endRv.y, 4)) .arg("\"" + entity.getText() + "\"")); // #TODO# Not The label } if (csvExp) { ts.writeString("\n%1;%2;%3;%4;%5;%6;%7;%8;%9;%10;%11;" .arg(nominator + id) // #TODO# Not relevant .arg(entity.getLayerName()) .arg(numberToString(posRv.x, 10)) .arg(numberToString(posRv.y, 10)) .arg(numberToString(aux1Rv.x, 10)) .arg(numberToString(aux1Rv.y, 10)) .arg(numberToString(startRv.x, 10)) .arg(numberToString(startRv.y, 10)) .arg(numberToString(endRv.x, 10)) .arg(numberToString(endRv.y, 10)) .arg("\"" + entity.getText() + "\"")); // #TODO# Not The label } idp++; ids.splice(i,1); idn--; } } firstOtype = true; // CVH added image entity types for (i=idn-1; i>=0; i--) { // Cycle through all remaining id = ids[i]; entity = document.queryEntity(id); if (isImageEntity(entity)) { if (firstOtype) { // Type header if (dmpCom) {EAction.handleUserMessage("Image dump:");} if (csvExp) {ts.writeString("\n\nImage dump:\nNominator; Layer; Position x; y; Angle; Height; Width; Fade; Filename;");} firstOtype = false; } posRv = entity.getInsertionPoint(); var test0 = 0; if ( 1<0 ) { test0 = entity.angle() + entity.getAngle(); } var test1 = entity.getUVector().x; var test2 = entity.getUVector().x; var test3 = entity.getVVector().y; var test4 = entity.getVVector().y; if (dmpCom) { // #TODO# Image Angle EAction.handleUserMessage("Img;%1;%2;%3;%4;%5;" .arg(numberToString(posRv.x, 4)) .arg(numberToString(posRv.y, 4)) .arg(numberToString(entity.getHeight(), 4)) .arg(numberToString(entity.getWidth(), 4)) .arg(entity.getFileName())); } // Radians! Multiply with Math.PI/2 for degrees if (csvExp) { ts.writeString("\nImg;%1;%2;%3;%4;%5;%6;%7;%8;" .arg(entity.getLayerName()) .arg(numberToString(posRv.x, 10)) .arg(numberToString(posRv.y, 10)) .arg("no angle yet") .arg(numberToString(entity.getHeight(), 10)) .arg(numberToString(entity.getWidth(), 10)) .arg(entity.getFade()) .arg(entity.getFileName())); } idp++; ids.splice(i,1); idn--; } } // firstOtype = true; // To copy block of code if (dmpCom) {EAction.handleUserInfo("+++++ Dump END +++++");} if (csvExp) { ts.writeString("\n\nEntities exported: " + idp + " of " + idCount); ts.writeString("\n+++ Dump END +++"); file.close(); EAction.handleUserMessage("Saved File: " + fileName) } EAction.activateMainWindow(); this.terminate(); }; // CVH kept: Orientation test as descibed in https://en.wikipedia.org/wiki/Curve_orientation // Was part of ExDumpPolyline.js in earlier QCAD update // Find minimum Vertex.x with minimum Vertex.y // The orientation at that point will be the orientation off a Simple Polygon // // FAULTY ### DocBasicEntities.isClockwise = function(poly) { var vn = poly.countVertices(); var vMin = RVector.invalid; var vBefore, vAfter; for (var k=0; k