QCAD 代码片段(二)

QCAD 代码片段

引用块对象的递归加载

引用块对象绘制统一返回圆。

//RBlockReferenceEntity.cpp
void RBlockReferenceEntity::exportEntity(RExporter& e, bool preview, bool forceSelected) const {
    
    e.setBrush(Qt::NoBrush);
    //绘制一个半径为1,圆心为对象位置的circle
    e.exportCircle(RCircle(data.getPosition().x,data.getPosition().y,1));
}

引用块对象包围盒的计算。

//RBlockReferenceData.cpp
QList<RBox> RBlockReferenceData::getBoundingBoxes(bool ignoreEmpty) const {
    QList<RBox>* bbs;
    if (ignoreEmpty) {
        bbs = &boundingBoxes;
    }
    else {
        bbs = &boundingBoxesIgnoreEmpty;
    }

    if (!bbs->isEmpty()) {
        return *bbs;
    }

    if (document == NULL) {
        return QList<RBox>();
    }

    RCircle r(position.x,position.y,1);
    bbs->append(r.getBoundingBox());
    return *bbs;
}

引用块对象几何数据的获取。

//RBlockReferenceData.cpp
QList<QSharedPointer<RShape> > RBlockReferenceData::getShapes(const RBox& queryBox, bool ignoreComplex, bool segment) const {
    Q_UNUSED(segment)
    return QList<QSharedPointer<RShape> >() <<
            QSharedPointer<RShape>(new RCircle(position.x,position.y,1));
}

限制递归深度为1。

//全局查找修改
static int recursionDepth = 0;
recursionDepth++;

if (recursionDepth>1) {
    recursionDepth--;
    return;
}

主题的加载

主题的加载,只加载css文件即可。

//library.js
function applyTheme() {
    var theme = RSettings.getValue("Theme/ThemeName", undefined);
    if (!isNull(theme)) {
        var path = "themes/" + theme + "/";

        qApp.styleSheet = "";

        // load stylesheet.css, stylesheet_[win|macos|linux].css:
        var found = false;
        var systemId = RS.getSystemId();
        if (systemId==="osx") systemId = "macos";

        var postfixes = ["", "_" + systemId];
        for (var i=0; i<postfixes.length; i++) {
            var postfix = postfixes[i];
            var fn = path + "stylesheet" + postfix + ".css";
            //qDebug("trying to load theme stylesheet: ", fn);

            if (new QFileInfo(fn).exists()) {
                var css = readTextFile(fn);
                // if (css.contains("RequiresPlugin:true")) {
                //     // only load theme if plugin loaded:
                //     var pluginId = theme.toUpperCase() + "STYLE";
                //     if (!RPluginLoader.hasPlugin(pluginId)) {
                //         qWarning("Theme not loaded: ", theme);
                //         qWarning("Theme plugin not found:", pluginId);
                //         return;
                //     }
                // }

                //css = css.replace(/url\\(/g, "url(" + path);
               // qDebug(css);
                qApp.styleSheet = qApp.styleSheet + "\\n" + css;
                found = true;
            }
        }

        // if (!found) {
        //     if (theme!=="Default") {
        //         qWarning("Cannot open theme: ", theme);
        //     }
        // }
    }
}

删减不必要的Js插件

Js插件一部分放在安装目录下,一部分编译成插件放在安装目录下的插件目录中。
删减插件中js脚本,只需从\\src\\scripts\\scripts_release.qrc删除即可。

\\src\\scripts\\scripts_release.qrc:为release版本下加载的插件。
\\src\\scripts\\scripts.qrc:为完整版本下加载的插件。

删减不必要程序配置选项的内容

【编辑】->【程序选项】/【绘制选项】

将Js脚本中的一下代码注释掉即可:

//示例:Exploade.js注释掉`getPreferencesCategory`函数即可。
// Explode.getPreferencesCategory = function() {
//     return [qsTr("Extensions"), qsTr("Explode")];
// };

目标图层与原图层分开

RLayer添加字段及函数

//RLayer.h
bool getLyType() const
{
    return lyType;
}

void setLyType(bool value)
{
    lyType = value;
}
private:
    bool lyType;

Js环境可调用

Js环境下可调用,需要封装转换一下,如果对象涉及到智能指针,需要转换两次。示例,REcma*.h&cpp 和REcmaSharedPointer*.h&cpp

//REcmaLayer.h & REcmaSharedPointerLayer.h
static  QScriptValue getLyType(QScriptContext* context, QScriptEngine* engine);

static  QScriptValue setLyType(QScriptContext* context, QScriptEngine* engine);
//REcmaLayer.cpp & REcmaSharedPointerLayer.cpp
 REcmaHelper::registerFunction(&engine, proto, getLyType, "getLyType");
REcmaHelper::registerFunction(&engine, proto, setLyType, "setLyType");

QScriptValue REcmaLayer::getLyType(QScriptContext *context, QScriptEngine *engine)
{

    //REcmaHelper::functionStart("REcmaLayer::getLyType", context, engine);
    //qDebug() << "ECMAScript WRAPPER: REcmaLayer::getLyType";
    //QCoreApplication::processEvents();

    QScriptValue result = engine->undefinedValue();

    // public function: can be called from ECMA wrapper of ECMA shell:
    RLayer* self =
            getSelf("getLyType", context);


    //Q_ASSERT(self!=NULL);
    if (self==NULL) {
        return REcmaHelper::throwError("self is NULL", context);
    }


    if( context->argumentCount() ==
            0
            ){
        // prepare arguments:

        // end of arguments

        // call C++ function:
        // return type 'bool'
        bool cppResult =

                self->getLyType();
        // return type: bool
        // standard Type
        result = QScriptValue(cppResult);

    } else

    {
        return REcmaHelper::throwError("Wrong number/types of arguments for RLayer.getLyType().",
                                    context);
    }
    //REcmaHelper::functionEnd("REcmaLayer::getLyType", context, engine);
    return result;
}

QScriptValue REcmaLayer::setLyType(QScriptContext *context, QScriptEngine *engine)
{
    //REcmaHelper::functionStart("REcmaLayer::setLyType", context, engine);
    //qDebug() << "ECMAScript WRAPPER: REcmaLayer::setLyType";
    //QCoreApplication::processEvents();

    QScriptValue result = engine->undefinedValue();

    // public function: can be called from ECMA wrapper of ECMA shell:
    RLayer* self =
            getSelf("setLyType", context);


    //Q_ASSERT(self!=NULL);
    if (self==NULL) {
        return REcmaHelper::throwError("self is NULL", context);
    }


    if( context->argumentCount() ==
            1 && (
                context->argument(0).isBool()
                ) /* type: bool */

            ){
        // prepare arguments:

        // argument isStandardType
        bool
                a0 =
                (bool)

                context->argument( 0 ).
                toBool();

        // end of arguments

        // call C++ function:
        // return type 'void'

        self->setLyType(a0);
    } else

    {
        return REcmaHelper::throwError("Wrong number/types of arguments for RLayer.setLyType().",
                                    context);
    }
    //REcmaHelper::functionEnd("REcmaLayer::setLyType", context, engine);
    return result;
}

修改图层列表Js脚本

\\scripts\\Widgets\\LayerList\\LayerList.js

//添加一个目标图层List控件,并初始化
    var layerListDest = new RLayerListQt(layout,RLayerListQt.Type.Dest);
    layerListDest.objectName = "DestLayerList";

    layout.addWidget(layerListDest,1,0);
    layout.addStretch();
    WidgetFactory.initList(layerListDest, "LayerList");
//设置事件处理函数,条目选择事件处理函数
    layerListDest.itemSelectionChanged.connect(function() {
        var action = RGuiAction.getByScriptFile("scripts/Layer/RemoveLayer/RemoveLayer.js");
        if (isNull(action)) {
            return;
        }

        var list = layerList.selectedItems();
        if (list.length === 0) {
            return;
        }

        var item = list[0];
        if (isNull(item)) {
            return;
        }

        // protected layers:
        if (item.text() === "0" || item.data(Qt.UserRole)===true) {
            action.setEnabledOverride(false, 0);
        } else {
            action.setEnabledOverride(true, 1);
        }       
    });

图层数目发生改变时,通过判断前面设置的字段来区分。

//`\\scripts\\Widgets\\LayerList\\LayerList.js`
RLayerListQt.prototype.updateLayers = function(documentInterface, previousLayerId) {
    this.di = documentInterface;
    var layer;

    var pos = this.verticalScrollBar().sliderPosition;
    this.clear();
    if (isNull(documentInterface)) {
        return;
    }

    var doc = documentInterface.getDocument();

    var result = doc.queryAllLayers();
    for ( var i = 0; i < result.length; ++i) {
        var id = result[i];
        layer = doc.queryLayer(id);

        if (layer.isNull()) {
            continue;
        }
        //图层区分
        if(this.lyType==RLayerListQt.Type.Src && layer.getLyType()==false){
            this.addLayerItem(layer);
        }
        if(this.lyType==RLayerListQt.Type.Dest && layer.getLyType()==true){
            this.addLayerItem(layer);
        }
    }
    this.sortItems();

    layer = doc.queryCurrentLayer();
    if (!layer.isNull()) {
        var items = this.findItems(layer.getName(), Qt.MatchExactly);
        if (items.length !== 0) {
            this.blockSignals(true);
            this.setCurrentItem(items[0]);
            this.blockSignals(false);
        }
    }
    this.verticalScrollBar().sliderPosition = pos;
};

加载dxf中文乱码

dxf文件为文本文件,中文编码可能是utf-8编码,也有可能是GBK编码。QCAD使用Qt开发环境,字符串统一按照utf-8编码解码,
所以解析dxf文件时对字符串首先按照utf-8转码,如果转码失败则按照GBK转码。

//RDxfImporter.cpp
QString decode(const std::string& str) {
    //GBK UTF-8->Unicode
    QByteArray data=QByteArray::fromStdString(str);
    QTextCodec::ConverterState state;
    QTextCodec *codec = QTextCodec::codecForName("UTF-8");
    QString str_tmp=codec->toUnicode(data.constData(),data.size(),&state);
    if(state.invalidChars>0){
        str_tmp=QTextCodec::codecForName("GBK")->toUnicode(data);
    }else{
        str_tmp=data;
    }
    return RDxfServices::parseUnicode(str_tmp);
}
//示例,可能出现乱码的地方需要调用一下
void RDxfImporter::addLayer(const DL_LayerData& data) {
    QString layerName = decode(data.name.c_str());
    
}
void RDxfImporter::addLinetype(const DL_LinetypeData& data) {
    QString name = decode(data.name.c_str());
    QString description = decode(data.description.c_str());
}

void RDxfImporter::addBlock(const DL_BlockData& data) {
    QString blockName = decode(data.name.c_str());
}
...
...
...

重建空间索引

1.文本字体的设置统一设置为 “Arial”。
2. 多线程处理对象的包围盒。

//RDocument.cpp 
void RDocument::rebuildSpatialIndex() {
    clearSpatialIndices();

    QSet<REntity::Id> result = storage.queryAllEntities(false, true);

    QList<int> allIds;
    QList<QList<RBox> > allBbs;
    QMap<RBlock::Id, QList<int> > allIdsByBlock;
    QMap<RBlock::Id, QList<QList<RBox> > > allBbsByBlock;

    QList<RIdBox > entities;
    QSetIterator<REntity::Id> j(result);
    while (j.hasNext()) {
        QSharedPointer<REntity> entity = storage.queryEntityDirect(j.next());
        if (entity.isNull()) {
            continue;
        }
        if (entity->isUndone()) {
            continue;
        }
        entity->update();
        int id=entity->getId();
        int blockId= entity->getBlockId();
        if(RS::EntityText==entity->getType()){
            RTextBasedEntity* txtEntity=(RTextBasedEntity*)(entity.data());
//            QString fontName=txtEntity->getFontName();
//            RFont*font=RFontList::get(fontName);
//            if(font==NULL){
//                continue;
//            }
            txtEntity->setFontName("Arial");
        }
        if(RS::EntityBlockRef==entity->getType()){
            continue;
//            QSharedPointer<RBlockReferenceEntity> blockRef = entity.dynamicCast<RBlockReferenceEntity>();
//            if (blockRef.isNull()) {
//                continue;
//            }
//            QVariant v = blockRef->getCustomProperty("", "block");
//            if (!v.isValid()) {
//                continue;
//            }
//            QString blockName = v.toString();
//            RBlock::Id refblockId = getBlockId(blockName);

//            if (refblockId==RBlock::INVALID_ID) {
//                continue;
//            }
//            blockRef->setReferencedBlockId(refblockId);
        }
        entity->update();
        entities.append(RIdBox(id,blockId,QList<RBox>(),entity));
    }
    QFuture<void>future= QtConcurrent::map(entities,&RDocument::buildSpatialIndex);
    future.waitForFinished();
    foreach (auto entity, entities) {
        if (disableSpatialIndicesByBlock) {
            allIds.append(entity.id);
            allBbs.append(entity.box);
        }
        else {
            RBlock::Id blockId = entity.blockId;

            if (!allIdsByBlock.contains(blockId)) {
                allIdsByBlock.insert(blockId, QList<int>());
            }
            allIdsByBlock[blockId].append(entity.id);

            if (!allBbsByBlock.contains(blockId)) {
                allBbsByBlock.insert(blockId, QList<QList<RBox> >());
            }
            allBbsByBlock[blockId].append(entity.box);
        }
    }
//    QSetIterator<REntity::Id> i(result);
//    while (i.hasNext()) {
//        QSharedPointer<REntity> entity = storage.queryEntityDirect(i.next());
//        if (entity.isNull()) {
//            continue;
//        }
//        if (entity->isUndone()) {
//            continue;
//        }

//        entity->update();

//        RObject::Id entityId = entity->getId();
//        QList<RBox> bbs = entity->getBoundingBoxes(true);
//        if (disableSpatialIndicesByBlock) {
//            allIds.append(entityId);
//            allBbs.append(bbs);
//        }
//        else {
//            RBlock::Id blockId = entity->getBlockId();

//            if (!allIdsByBlock.contains(blockId)) {
//                allIdsByBlock.insert(blockId, QList<int>());
//            }
//            allIdsByBlock[blockId].append(entityId);

//            if (!allBbsByBlock.contains(blockId)) {
//                allBbsByBlock.insert(blockId, QList<QList<RBox> >());
//            }
//            allBbsByBlock[blockId].append(bbs);
//        }
//    }

    if (!disableSpatialIndicesByBlock) {
        QList<RBlock::Id> blockIds = queryAllBlocks().toList();
        for (int i=0; i<blockIds.length(); i++) {
            RBlock::Id blockId = blockIds[i];
            RSpatialIndex* si = getSpatialIndexForBlock(blockId);

            // remove entries without bounding boxes:
            for (int i=allIdsByBlock[blockId].length()-1; i>=0 && !allIdsByBlock[blockId].isEmpty(); i--) {
                if (allBbsByBlock[blockId][i].isEmpty()) {
                    allIdsByBlock[blockId].removeAt(i);
                    allBbsByBlock[blockId].removeAt(i);
                }
            }

            si->bulkLoad(allIdsByBlock[blockId], allBbsByBlock[blockId]);
//            for (int i=0; i<allIdsByBlock[blockId].length(); i++) {
//                si->addToIndex(allIdsByBlock[blockId][i], allBbsByBlock[blockId][i]);
//            }
        }
    }
    else {
        spatialIndex.bulkLoad(allIds, allBbs);
    }

    // clear cached bounding box:
    storage.update();
}

国际化中文翻译

ts文件夹下,有成对的*.ts*.qm文件。示例:qcadextensions_zh_CN.tsqcadextensions_zh_CN.qm是插件
/src/support/examples/extensions插件的翻译文件。

对于支持国际化的插件,需要在项目.pro文件中添加如下内容:

//src/support/examples/extensions/extensions.pro
include( ../../../shared_ts.pri )

同时插件初始化时,加载对应的*.ts文件。

//src/support/examples/extensions/RExtensionsPlugin.h
void ExtensionsPlugin::initTranslations()
{
     RSettings::loadTranslations("qcadextensions", QStringList() << ":ts");
}

翻译宏标记

1.cpp 文件

QObject::tr("None")

2.js 文件

qsTr("None");

生成ts文件

QtCreator菜单【工具】->【外部->【Qt语言家】->【更新翻译】,更新翻译后,会在ts文件夹下生成对应的ts文件。

生成qm文件

利用Qt语言家(Linguist)打开ts文件,翻译后发布后,生成对应的qm文件,国际化支持完成。

图层列表和块列表标志图标显示

自定义一个RListWidgetDelegate类,继承自QStyledItemDelegate,需要重载paint函数,根据Item数据来自定义Item外观,实现图层列表和块列表显示标志图标。

//RListWidget.h
class RListWidgetDelegate:public QStyledItemDelegate
{
    Q_OBJECT
public:
    RListWidgetDelegate(QObject *parent):
        QStyledItemDelegate(parent){

    }
    virtual ~RListWidgetDelegate(){}


    // QAbstractItemDelegate interface
public:
    virtual void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
};

重载paint函数,绘制图标。

//RListWidget.cpp
void RListWidgetDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QStyledItemDelegate::paint(painter, option, index);
    QRect rect = option.rect;   // 目标矩形
    rect.adjust(2,2,-2,-2);     // 缩小一圈,留出空白间隔
    //Qt::UserRole+1,2,3保存图层的颜色值
    int r = index.data(Qt::UserRole+1).toInt();
    int g = index.data(Qt::UserRole+2).toInt();
    int b = index.data(Qt::UserRole+3).toInt();
    {
        //绘制图层颜色图标
        QColor clr(r,g,b);
        QRect dst = rect;
        dst.setLeft(rect.right()-60);
        QRect area(0,0,20,10);
        area.moveCenter(dst.center());
        painter->fillRect(area,clr);
        QPen pen(Qt::black);
        painter->setPen(pen);
        painter->drawRect(area);
    }
    //Qt::UserRole+4保存块图标
    QString filesvg=index.data(Qt::UserRole+4).toString();
    QFileInfo fileInfo(filesvg);
    //绘制块图标
    if(option.state & QStyle::State_Selected){
        if(fileInfo.isFile())
        {
            QRect dst = rect;
            dst.setLeft(rect.right()-120);
            QRect area(0,0,18,18);
            area.moveCenter(dst.center());

            QPixmap pixmapPic(filesvg);
            painter->drawPixmap(area, pixmapPic);
        }
    }
}

设置RListWidget控件的委托外观类。

//RListWidget.cpp
RListWidget::RListWidget(QWidget* parent) :
    QListWidget(parent), itemPressed(NULL), iconOffset(0) {
//#ifdef Q_OS_MAC
//    iconOffset = 7;
//#else
//    iconOffset = 0;
//#endif
    this->setItemDelegate(new RListWidgetDelegate(this));
    installEventFilter(new REventFilter(QEvent::KeyPress, true));
    installEventFilter(new REventFilter(QEvent::KeyRelease, true));
}

图层列表标志图标数据的设置。

//scripts\\Widgets\\LayerList\\LayerList.js
RLayerListQt.prototype.addLayerItem=function(layer){
    var item = new QListWidgetItem(layer.getName(), this);
    var iconName = autoIconPath(this.basePath
            + "/layerstatus_%1%2.svg".arg(Number(layer.isFrozen()))
            .arg(Number(layer.isLocked())));
    item.setIcon(new QIcon(iconName));
    //
    //var icon = RColor.getIcon(layer.getColor(), new QSize(20,10));
    //item.setIcon(icon);
    //
    item.setData(Qt.UserRole+1,layer.getColor().red());
    item.setData(Qt.UserRole+2,layer.getColor().green());
    item.setData(Qt.UserRole+3,layer.getColor().blue());
    item.setData(Qt.UserRole+4,this.basePath +"/EditLayer.svg");
    if (layer.isProtected()) {
        item.setData(Qt.UserRole, true);
    }
    this.addItem(item);
}

块列表标志图标的设置

//scripts\\Widgets\\BlockList\\BlockList.js
RBlockListQt.prototype.createBlockItem = function(block) {
    var item = new QTreeWidgetItem();
    var name = block.getName();

    var flags = new Qt.ItemFlags(Qt.ItemIsSelectable|Qt.ItemIsEnabled);
    item.setFlags(flags);

    var title = RBlockListQt.getBlockTitle(block);
    // count the blockReferences
    var doc = this.di.getDocument();
    var blockId=doc.getBlockId(name);
    var ids=doc.queryBlockReferences(blockId);

    if(ids.length>0 && blockId != 5){
        //title= sprintf("%s [ %d ]",title,ids.length);
        item.setData(BlockList.colName,Qt.UserRole+2,ids.length);
    }
    item.setText(BlockList.colName, title);
    item.setData(BlockList.colName, Qt.UserRole, name);
    this.updateItemIcons(item, block);
    var dirpath=sprintf("%s/images",RSettings.getApplicationPath());
    var dir=new QDir();
    if(dir.exists(dirpath))dir.mkpath(dirpath);
    var fileName=sprintf("%s/%s.png",dirpath,name);
    item.setData(BlockList.colName, Qt.UserRole+1, fileName);
    return item;
};

自定义属性读取与写入

自定义属性的读取,属性以字符串的方式保存,如:“property=value”。

//RDxfImporter.cpp
void RDxfImporter::importXData(QSharedPointer<REntity> entity)
{
    QStringList pJson;
    QString str;
    QPair<int,QVariant>p;

    foreach (const QString &group, xData.keys()) {
        QList<QPair<int, QVariant>> properties=xData.value(group);

        for(int i=0;i<properties.size();++i){
            p=properties.at(i);
            str=p.second.toString();
            if(str.contains('=')){
                 pJson=str.split("=");
                 if(pJson.length()>1){

                     entity->setProperty(RPropertyTypeId(group,pJson[0]),pJson[1]);
                     //qDebug()<<"group:"<<group<<"; key:"<<pJson[0]<<"; value:"<<pJson[1];
                     //设置自定义属性的属性,显示标签,以及可选项列表
                     QJsonObject field=getFieldAttri(group,pJson[0]);
                     RPropertyAttributes proAttr;
                     proAttr.setOption(RPropertyAttributes::Custom,true);
                     proAttr.setLabel(field.value("dataName").toString());
                     QString dic=field.value("dictionary").toString();
                     if(dic.length()>1){
                         QStringList items=dic.split(";");
                         QSet<QString>choices;
                         for(int i=0;i<items.count();i++){
                             QString item=items.at(i);
                             if(item.length()>1){
                                 QStringList choice=item.split(",");
                                 choices.insert(choice[1]);
                             }
                         }
                         if(choices.count()>0)
                             proAttr.setChoices(choices);
                     }
                     QString viewType=field.value("viewType").toString();
                     if(viewType=="MultLineTextBox")
                         proAttr.setRichText(true);
                     else if(viewType=="NumberTextBox")
                         proAttr.setOption(RPropertyAttributes::Integer,true);
                     entity->setCustomPropertyAttributes(group,pJson[0],proAttr);
                     //import to customtables;
                     document->addCustomTables(group,entity->getId());
                     //qDebug()<<"group:"<<group<<";entity:"<<entity->getId();
                 }
            }
        }

    }
}

自定义属性的写入

//RDxfExporter.cpp
void RDxfExporter::writeCustomProperties(const REntity& p)
{
    QMap<QString, QVariantMap>customProperties=p.getCustomProperties();
    QString kv;
    foreach (QString title, customProperties.keys()) {
        QVariantMap properties=customProperties.value(title);

        dw->dxfString(1001, (const char*)RDxfExporter::escapeUnicode(title));
        foreach (const QString key, properties.keys()) {
            QVariant value=properties.value(key);
            
            kv=QString("%1=%2").arg(key,value.toString());
            dw->dxfString(1000,(const char*)RDxfExporter::escapeUnicode(kv));
        }
    }
   // dxf.writeDictionaryEntry();
}

数据库使用

目标图层的保存

//NewFile.js 331
if(isOpen){
        //初始化数据库
        FileDB.initDb();
        var ids=LayerTypeTablePeer.getItems();
        for(var i=0;i<ids.length;++i){
            //这里是获取副本
            var layer=document.queryLayer(ids[i].name);
            if(!isNull(layer)){
                //获取引用
                layer=document.queryLayerDirect(layer.getId());
                layer.setLyType(true);
            }else{
                LayerTypeTablePeer.doDeleteById(ids[i].name);
            }
        }
        //
        ids=document.queryAllLayers();
        //通知图层改变信号
        appWin.notifyLayerListeners(documentInterface,ids);
    }

目标图层的设置

//FilterEditor.js 184
    var op=undefined;
    var layer=undefined;
    layer=doc.queryLayer(text);
    if(isNull(layer)){
        layer = new RLayer(doc, text, false, false, clr, ltId, lw);
        layer.setLyType(true);
        op = new RModifyObjectOperation(layer);
        di.applyOperation(op);
        
    }else{
        //获取图层引用,并修改其属性,注意不是副本
        layer=doc.queryLayerDirect(layer.getId());
        layer=layer.data();
        layer.setLyType(true);
    }
    //保存目标图层
    var layerType=new LayerTypeTable(layer.getName());
    layerType.save();
    //设置为当前图层
    di.setCurrentLayer(layer);

坐标转换

仿射变换

//RCoordsParamSettingWidget.cpp
void RCoordsParamSettingWidget::AffineTransform(double &x, double &y)
{
    double x1=x,y1=y;

    double dx=ui->leDX_2->text().toDouble();
    double dy=ui->leDY_2->text().toDouble();
    double angle=ui->leRX_2->text().toDouble();
    angle*= DEG_TO_RAD;
    double m=ui->lem_2->text().toDouble();
    x=dx+(m)*(cos(angle)*x1-sin(angle)*y1);
    y=dy+(m)*(sin(angle)*x1+cos(angle)*y1);

}

仿射变换改变实体形状

//RAffineTransImpl.cpp 194
void RAffineTransImpl::btnApplyClicked()
{
    if(_result.count()>0){
         emit calcResult(_result);
    }
    double rotation=ui->angleLineEdit->text().toDouble()*DEG_TO_RAD;
    double scale=ui->scaleLineEdit->text().toDouble();
    double x = ui->dXLineEdit->text().toDouble();
    double y = ui->dYLineEdit->text().toDouble();
    double a = scale * cos(rotation);
    double b = scale  * sin(rotation);
    QTransform *transform=new QTransform(a,b,x,-b,a,y,0,0,1);
    RDocumentInterface*di=RMainWindow::getDocumentInterfaceStatic();
    RDocument&doc=di->getDocument();
    QSet<REntity::Id>ids=doc.querySelectedEntities();
    if(ids.count()<1){
        QMessageBox::information(this,"提示","请选择变换的实体!");
    }
    RAddObjectsOperation*op=new RAddObjectsOperation();
    QSet<REntity::Id>::const_iterator it;
    for (it=ids.constBegin(); it!=ids.constEnd(); it++) {
        REntity::Id id=*it;
        QSharedPointer<REntity> entity=doc.queryEntity(id);
        RShape*shape=entity->castToShape();
        QSharedPointer<RShape>pShape=shape->getTransformed(transform->transposed());
        QSharedPointer<REntity>e=RCommonFunc::shapeToEntity(doc,pShape);
        e->copyAttributesFrom(entity->clone());
        op->deleteObject(entity);
        op->addObject(e,false);
    }
    di->applyOperation(op);
}

投影坐标转换为经纬度

//RCoordinateTransImpl.cpp
void RCoordinateTransImpl::coordTransform(double &x, double &y, double &z)
{
    int trans_type=parasetting->getTransType();
    //是否需要进行放射变换
    if(trans_type==1)
        parasetting->AffineTransform(x,y);
    pj_transform(pjsrc,pjdest,1,1,&x,&y,&z);
    x*=RAD_TO_DEG;
    y*=RAD_TO_DEG;
}

对选择的实体进行坐标转换

//RCoordinateTransImpl.cpp
RMainWindowQt *app= RMainWindowQt::getMainWindow();
RDocumentInterface*di =app->getDocumentInterface();
if(di){
    RDocument&doc=di->getDocument();
    QSet<REntity::Id>ids= doc.querySelectedEntities();
    QSet<REntity::Id>::const_iterator it;
    QSharedPointer<REntity> entity;
    for(it=ids.constBegin();it!=ids.constEnd();it++){
        REntity::Id id=*it;
        entity=doc.queryEntityDirect(id);
        RBox box=entity->getBoundingBox();
        RVector v=box.getCenter();
        double x=v.x,y=v.y,z=0.0;
        coordTransform(x,y,z);
        entity->setProperty(RPropertyTypeId("app","lon"),x);
        entity->setProperty(RPropertyTypeId("app","lat"),y);
    }
    QMessageBox::information(this,"提示",QString("%1条数据转换完毕。").arg(ids.count()),
                                QMessageBox::StandardButton::Ok);
}

数据导出Excel sheet

//RExportExcelImpl.cpp 
void RExportExcelImpl::exportSheet(QJsonObject dataObj)
{
    RDocument*doc=appWin->getDocument();

    QXlsx::Workbook* workBook= xlsx.workbook();
    QJsonArray  fields=dataObj.value("dataFields").toArray();
    QString group=dataObj.value("emCode").toString();
    QString sheetName=dataObj.value("emName").toString();
    QString dataType=dataObj.value("objectType").toString();
    QSet<REntity::Id>ids=doc->getCustomTableValues(group);
    if(ids.count()<1)
        return;
    sheetName=QString("%1(%2)").arg(sheetName).arg(ids.count());
    QXlsx::Worksheet* workSheet=static_cast<QXlsx::Worksheet*>(workBook->addSheet(sheetName));
    int col;
    if(dataType=="POINT"){
        col=1;
        workSheet->write(1,col++,"序号");
        workSheet->write(1,col++,"系统编号");
        workSheet->write(1,col++,"创建时间");
        workSheet->write(1,col++,"解状态");
        workSheet->write(1,col++,"经度");
        workSheet->write(1,col++,"纬度");
        workSheet->write(1,col++,"高程");
        workSheet->write(1,col++,"城建坐标N");
        workSheet->write(1,col++,"城建坐标E");
        workSheet->write(1,col++,"城建坐标H");

        for(int i=0;i<fields.count();++i){
            QJsonObject field=fields.at(i).toObject();
            workSheet->write(1,col++,field.value("dataName").toString());
        }

        int row=2;
        QSet<REntity::Id>::const_iterator it;
        QSharedPointer<REntity> entity;
        for(it=ids.constBegin();it!=ids.constEnd();it++){

            REntity::Id id=*it;
            entity=doc->queryEntityDirect(id);
            col=1;
            workSheet->write(row,col++,row-1);
            QString uuid=entity->getCustomProperty(group,"uuid").toString();
            workSheet->write(row,col++,uuid);
            workSheet->write(row,col++,QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
            //解状态
            workSheet->write(row,col++," ");
            QString lon="-1",lat="-1";
            lon=entity->getCustomProperty("app","lon").toString();
            lat=entity->getCustomProperty("app","lat").toString();
            //经度
            workSheet->write(row,col++,lon);
            //纬度
            workSheet->write(row,col++,lat);
            //高程
            workSheet->write(row,col++," ");
            //平面坐标
            RBox box=entity->getBoundingBox();
            RVector v= box.getCenter();
            workSheet->write(row,col++,v.y);
            workSheet->write(row,col++,v.x);
            workSheet->write(row,col++,v.z);
            //写入动态字段
            for(int i=0;i<fields.count();++i){
                QJsonObject field=fields.at(i).toObject();
                QString title=field.value("dataCode").toString();
                QString value=entity->getCustomProperty(group,title).toString();
                workSheet->write(row,col++,value);
            }
            row++;
        }

    }
    else if(dataType=="LINE"){
        col=1;
        workSheet->write(1,col++,"序号");
        workSheet->write(1,col++,"系统编号");
        workSheet->write(1,col++,"管线长度");
        workSheet->write(1,col++,"压力级别");
        workSheet->write(1,col++,"创建时间");
        workSheet->write(1,col++,"起点编号");
        workSheet->write(1,col++,"起点经度");
        workSheet->write(1,col++,"起点纬度");
        workSheet->write(1,col++,"起点高程");
        workSheet->write(1,col++,"终点编号");
        workSheet->write(1,col++,"终点经度");
        workSheet->write(1,col++,"终点纬度");
        workSheet->write(1,col++,"终点高程");
        workSheet->write(1,col++,"起点城建坐标N");
        workSheet->write(1,col++,"起点城建坐标E");
        workSheet->write(1,col++,"起点城建坐标H");
        workSheet->write(1,col++,"终点城建坐标N");
        workSheet->write(1,col++,"终点城建坐标E");
        workSheet->write(1,col++,"终点城建坐标H");

        for(int i=0;i<fields.count();++i){
            QJsonObject field=fields.at(i).toObject();
            workSheet->write(1,col++,field.value("dataName").toString());
        }
        int row=2;
        QSet<REntity::Id>::const_iterator it;
        QSharedPointer<REntity> entity;

        for(it=ids.constBegin();it!=ids.constEnd();it++){

            REntity::Id id=*it;
            entity=doc->queryEntityDirect(id);
            col=1;
            workSheet->write(row,col++,row-1);
            QString uuid=entity->getCustomProperty(group,"uuid").toString();
            workSheet->write(row,col++,uuid);
            QSharedPointer<RLineEntity>line= entity.dynamicCast<RLineEntity>();
            QString length="-1";
            if(line->isValid()){
                length=QString("%1").arg(line->getLength());
            }
            workSheet->write(row,col++,length);
            //压力级别
            QString value=entity->getCustomProperty(group,"pressureRange").toString();
            workSheet->write(row,col++,value);
            //qDebug()<<"压力级别:"<<value;
            //创建时间
            workSheet->write(row,col++,QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss"));
            //起点编号
            REntity::Id start_id =entity->getCustomProperty(group,"start").toInt();
            QSharedPointer<REntity>start_entity=doc->queryEntityDirect(start_id);
            value="-1";
            QString lon="-1",lat="-1";
            if(!start_entity.isNull()&&start_entity->isValid()){
                QString start_group=start_entity->getCustomProperty("app","group").toString();
                value=start_entity->getCustomProperty(start_group,"uuid").toString();
                lon=start_entity->getCustomProperty("app","lon").toString();
                lat=start_entity->getCustomProperty("app","lat").toString();
            }
            //!起点
            workSheet->write(row,col++,value);
            //经度
            workSheet->write(row,col++,lon);
            //纬度
            workSheet->write(row,col++,lat);
            //高程
            workSheet->write(row,col++," ");
            REntity::Id end_id=entity->getCustomProperty(group,"end").toInt();
            QSharedPointer<REntity>end_entity=doc->queryEntityDirect(end_id);
            value="-1";
            if(!end_entity.isNull()&& end_entity->isValid()){
                QString end_group=end_entity->getCustomProperty("app","group").toString();
                value=end_entity->getCustomProperty(end_group,"uuid").toString();
                lon=end_entity->getCustomProperty("app","lon").toString();
                lat=end_entity->getCustomProperty("app","lat").toString();
            }
            //!终点
            workSheet->write(row,col++,value);
            //经度
            workSheet->write(row,col++,lon);
            //纬度
            workSheet->write(row,col++,lat);
            //高程
            workSheet->write(row,col++," ");
            //平面坐标
            RVector v;
            if(line->isValid()){
                v= line->getStartPoint();
            }
            workSheet->write(row,col++,v.y);
            workSheet->write(row,col++,v.x);
            workSheet->write(row,col++,v.z);
            if(line->isValid()){
                v= line->getEndPoint();
            }
            workSheet->write(row,col++,v.y);
            workSheet->write(row,col++,v.x);
            workSheet->write(row,col++,v.z);
            //写入动态字段
            for(int i=0;i<fields.count();++i){
                QJsonObject field=fields.at(i).toObject();
                QString title=field.value("dataCode").toString();
                value=entity->getCustomProperty(group,title).toString();
                workSheet->write(row,col++,value);
            }
            row++;
       }
    }

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片

    暂无评论内容