void MoleculeJsonSaver::saveMetaData()

in core/indigo-core/molecule/src/molecule_json_saver.cpp [1806:2080]


void MoleculeJsonSaver::saveMetaData(JsonWriter& writer, MetaDataStorage& meta)
{
    static const std::unordered_map<int, std::string> _arrow_type2string = {
        {ReactionComponent::ARROW_BASIC, "open-angle"},
        {ReactionComponent::ARROW_FILLED_TRIANGLE, "filled-triangle"},
        {ReactionComponent::ARROW_FILLED_BOW, "filled-bow"},
        {ReactionComponent::ARROW_DASHED, "dashed-open-angle"},
        {ReactionComponent::ARROW_FAILED, "failed"},
        {ReactionComponent::ARROW_BOTH_ENDS_FILLED_TRIANGLE, "both-ends-filled-triangle"},
        {ReactionComponent::ARROW_EQUILIBRIUM_FILLED_HALF_BOW, "equilibrium-filled-half-bow"},
        {ReactionComponent::ARROW_EQUILIBRIUM_FILLED_TRIANGLE, "equilibrium-filled-triangle"},
        {ReactionComponent::ARROW_EQUILIBRIUM_OPEN_ANGLE, "equilibrium-open-angle"},
        {ReactionComponent::ARROW_UNBALANCED_EQUILIBRIUM_FILLED_HALF_BOW, "unbalanced-equilibrium-filled-half-bow"},
        {ReactionComponent::ARROW_UNBALANCED_EQUILIBRIUM_LARGE_FILLED_HALF_BOW, "unbalanced-equilibrium-large-filled-half-bow"},
        {ReactionComponent::ARROW_BOTH_ENDS_FILLED_TRIANGLE, "unbalanced-equilibrium-filled-half-triangle"},
        {ReactionComponent::ARROW_RETROSYNTHETIC, "retrosynthetic"}};

    const auto& meta_objects = meta.metaData();
    for (int meta_index = 0; meta_index < meta_objects.size(); ++meta_index)
    {
        auto pobj = meta_objects[meta_index];
        switch (pobj->_class_id)
        {
        case ReactionArrowObject::CID: {
            ReactionArrowObject& ar = (ReactionArrowObject&)(*pobj);
            writer.StartObject();
            writer.Key("type");
            writer.String("arrow");
            writer.Key("data");
            writer.StartObject();
            // arrow mode
            writer.Key("mode");
            std::string arrow_mode = "open-angle";
            auto at_it = _arrow_type2string.find(ar.getArrowType());
            if (at_it != _arrow_type2string.end())
                arrow_mode = at_it->second.c_str();
            writer.String(arrow_mode.c_str());

            // arrow coordinates
            writer.Key("pos");
            writer.StartArray();
            writer.StartObject();
            writer.Key("x");
            writeFloat(writer, ar.getTail().x);
            writer.Key("y");
            writeFloat(writer, ar.getTail().y);
            writer.Key("z");
            writer.Double(0);
            writer.EndObject();

            writer.StartObject();
            writer.Key("x");
            writeFloat(writer, ar.getHead().x);
            writer.Key("y");
            writeFloat(writer, ar.getHead().y);
            writer.Key("z");
            writer.Double(0);
            writer.EndObject();

            writer.EndArray();  // arrow coordinates
            writer.EndObject(); // end data
            writer.EndObject(); // end node
        }
        break;
        case ReactionMultitailArrowObject::CID: {
            ReactionMultitailArrowObject& ar = (ReactionMultitailArrowObject&)(*pobj);
            writer.StartObject();
            writer.Key("type");
            writer.String("multi-tailed-arrow");
            writer.Key("data");
            writer.StartObject();

            writer.Key("head");
            writer.StartObject();
            writer.Key("position");
            writer.StartObject();
            writer.Key("x");
            writeFloat(writer, ar.getHead().x);
            writer.Key("y");
            writeFloat(writer, ar.getHead().y);
            writer.Key("z");
            writer.Double(0);
            writer.EndObject();
            writer.EndObject();

            writer.Key("spine");
            writer.StartObject();
            writer.Key("pos");
            writer.StartArray();

            writer.StartObject();
            writer.Key("x");
            writeFloat(writer, ar.getSpineBegin().x);
            writer.Key("y");
            writeFloat(writer, ar.getSpineBegin().y);
            writer.Key("z");
            writer.Double(0);
            writer.EndObject();

            writer.StartObject();
            writer.Key("x");
            writeFloat(writer, ar.getSpineEnd().x);
            writer.Key("y");
            writeFloat(writer, ar.getSpineEnd().y);
            writer.Key("z");
            writer.Double(0);
            writer.EndObject();

            writer.EndArray();
            writer.EndObject();

            writer.Key("tails");
            writer.StartObject();
            writer.Key("pos");
            writer.StartArray();

            for (auto& t : ar.getTails())
            {
                writer.StartObject();
                writer.Key("x");
                writeFloat(writer, t.x);
                writer.Key("y");
                writeFloat(writer, t.y);
                writer.Key("z");
                writer.Double(0);
                writer.EndObject();
            }

            writer.EndArray();
            writer.EndObject();

            writer.Key("zOrder");
            writer.Int(0);

            writer.EndObject();
            writer.EndObject();
        }
        break;
        case ReactionPlusObject::CID: {
            ReactionPlusObject& rp = (ReactionPlusObject&)(*pobj);
            writer.StartObject();
            writer.Key("type");
            writer.String("plus");
            writer.Key("location");
            writer.StartArray();
            writeFloat(writer, rp.getPos().x);
            writeFloat(writer, rp.getPos().y);
            writer.Double(0);
            writer.EndArray();
            writer.EndObject();
        }
        break;
        case SimpleGraphicsObject::CID: {
            auto simple_obj = (SimpleGraphicsObject*)pobj;
            writer.StartObject();
            writer.Key("type");
            writer.String("simpleObject");
            writer.Key("data");
            writer.StartObject();
            writer.Key("mode");
            switch (simple_obj->_mode)
            {
            case SimpleGraphicsObject::EEllipse:
                writer.String("ellipse");
                break;
            case SimpleGraphicsObject::ERectangle:
                writer.String("rectangle");
                break;
            case SimpleGraphicsObject::ELine:
                writer.String("line");
                break;
            }
            writer.Key("pos");
            writer.StartArray();

            auto& coords = simple_obj->_coordinates;

            // point1
            writer.StartObject();
            writer.Key("x");
            writeFloat(writer, coords.first.x);
            writer.Key("y");
            writeFloat(writer, coords.first.y);
            writer.Key("z");
            writer.Double(0);
            writer.EndObject();

            // point2
            writer.StartObject();
            writer.Key("x");
            writeFloat(writer, coords.second.x);
            writer.Key("y");
            writeFloat(writer, coords.second.y);
            writer.Key("z");
            writer.Double(0);
            writer.EndObject();

            writer.EndArray();

            // end data
            writer.EndObject();
            // end node
            writer.EndObject();
            break;
        }
        case SimpleTextObject::CID: {
            auto simple_obj = (SimpleTextObject*)pobj;
            writer.StartObject();
            writer.Key("type");
            writer.String("text");
            writer.Key("data");
            writer.StartObject();
            writer.Key("content");
            writer.String(simple_obj->_content.c_str());
            writer.Key("position");
            writePos(writer, simple_obj->_pos);

            writer.Key("pos");
            writer.StartArray();
            Vec2f pos_bbox(simple_obj->_pos.x, simple_obj->_pos.y);
            writePos(writer, pos_bbox);
            pos_bbox.y -= simple_obj->_size.y;
            writePos(writer, pos_bbox);
            pos_bbox.x += simple_obj->_size.x;
            writePos(writer, pos_bbox);
            pos_bbox.y += simple_obj->_size.y;
            writePos(writer, pos_bbox);
            writer.EndArray();
            writer.EndObject(); // end data
            writer.EndObject(); // end node
            break;
        }
        case EmbeddedImageObject::CID: {
            auto image_obj = static_cast<const EmbeddedImageObject*>(pobj);
            auto& bbox = image_obj->getBoundingBox();
            writer.StartObject(); // start node
            writer.Key("type");
            writer.String("image");
            writer.Key("format");
            switch (image_obj->getFormat())
            {
            case EmbeddedImageObject::EKETPNG:
                writer.String(KImagePNG);
                break;
            case EmbeddedImageObject::EKETSVG:
                writer.String(KImageSVG);
                break;
            default:
                throw Exception("Bad image format: %d", image_obj->getFormat());
            }

            writer.Key("boundingBox");

            writer.StartObject(); // start bbox
            writer.Key("x");
            writeFloat(writer, bbox.left());
            writer.Key("y");
            writeFloat(writer, bbox.top());
            writer.Key("z");
            writer.Double(0);

            writer.Key("width");
            writeFloat(writer, bbox.width());
            writer.Key("height");
            writeFloat(writer, bbox.height());
            writer.EndObject(); // end bbox

            writer.Key("data");
            writer.String(image_obj->getBase64().c_str());
            writer.EndObject(); // end node
            break;
        }
        }
    }
}