Skip to content

Commit

Permalink
add atom label margin
Browse files Browse the repository at this point in the history
  • Loading branch information
AleksandrParamonoff committed Sep 12, 2024
1 parent f519b48 commit a08e208
Show file tree
Hide file tree
Showing 10 changed files with 764 additions and 547 deletions.
1 change: 1 addition & 0 deletions api/c/indigo/src/option_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "base_cpp/red_black.h"

#include <sstream>
#include <stdint.h>

using namespace indigo;

Expand Down
87 changes: 48 additions & 39 deletions api/c/tests/unit/tests/layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,50 +45,59 @@ class IndigoApiLayoutTest : public IndigoApiTest
indigoRendererDispose(session);
IndigoApiTest::TearDown();
}
};

TEST_F(IndigoApiLayoutTest, one_reactant_one_product)
{
indigoSetErrorHandler(errorHandler, nullptr);

indigoSetOption("render-coloring", "true");
indigoSetOption("render-stereo-style", "none");
indigoSetOptionXY("render-image-size", 400, 400);
indigoSetOption("render-output-format", "png");

indigoSetOptionBool("json-saving-pretty", true);
try
struct TestCaseResult
{
auto rc = indigoLoadReactionFromFile(dataPath("molecules/basic/before_layout.ket").c_str());
std::string_view result;
std::string_view expected;
};

indigoLayout(rc);
TestCaseResult applyLayoutAndGetResult(int reactionId, std::string_view expectedResultFilename)
{
indigoSetOptionBool("json-saving-pretty", true);
indigoSetOptionBool("json-use-native-precision", true);
indigoSetOptionBool("json-saving-add-stereo-desc", true);

const char* res = indigoJson(rc);
// printf("res=%s", res);
std::ifstream is(dataPath("molecules/basic/after_layout.ket"), std::ios::binary | std::ios::ate);
indigoLayout(reactionId);
// indigoSaveJsonToFile(reactionId, expectedResultFilename.data());
std::string path_to_file = "molecules/basic/" + std::string(expectedResultFilename);
std::ifstream is(dataPath(path_to_file.data()), std::ios::binary | std::ios::ate);
auto size = is.tellg();
std::string str(size, '\0'); // construct string to stream size
stringBuffer = std::string(size, '\0'); // construct string to stream size
is.seekg(0);
is.read(&str[0], size);
str.erase(std::remove(str.begin(), str.end(), '\r'), str.end());
is.read(&stringBuffer[0], size);
stringBuffer.erase(std::remove(stringBuffer.begin(), stringBuffer.end(), '\r'), stringBuffer.end());

// ASSERT_STREQ(res, str.c_str());
indigoSaveJsonToFile(rc, "res_after_layout.ket");
{
indigoSetOption("reaction-component-margin-size", "0.0");
indigoLayout(rc);
indigoSaveJsonToFile(rc, "res_after_layout2.ket");
}
{
indigoSetOption("reaction-component-margin-size", "3.2");
indigoLayout(rc);
indigoSaveJsonToFile(rc, "res_after_layout3.ket");
}

indigoFree(rc);
}
catch (Exception& e)
{
ASSERT_STREQ("", e.message());
const char* res = indigoJson(reactionId);
return {res, stringBuffer};
}
}
std::string stringBuffer;
};
//
//TEST_F(IndigoApiLayoutTest, check_reaction_margin_size)
//{
// indigoSetErrorHandler(errorHandler, nullptr);
// indigoSetOptionBool("json-saving-pretty", true);
// indigoSetOptionBool("json-use-native-precision", true);
// indigoSetOptionBool("json-saving-add-stereo-desc", true);
// try
// {
// auto reactionId = indigoLoadReactionFromFile(dataPath("molecules/basic/before_layout.ket").c_str());
// {
// indigoSetOption("reaction-component-margin-size", "0.0");
// auto files = applyLayoutAndGetResult(reactionId, "after_layout_zero_margin.ket");
// EXPECT_STREQ(files.result.data(), files.expected.data());
// }
// {
// indigoSetOption("bond-length", "40.0");
// indigoSetOption("reaction-component-margin-size", "20.0");
// auto files = applyLayoutAndGetResult(reactionId, "after_layout_default_margin.ket");
// EXPECT_STREQ(files.result.data(), files.expected.data());
// }
// indigoFree(reactionId);
// }
// catch (Exception& e)
// {
// ASSERT_STREQ("", e.message());
// }
//}
9 changes: 7 additions & 2 deletions core/indigo-core/layout/metalayout.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@

#include "base_cpp/obj_array.h"
#include "base_cpp/reusable_obj_array.h"

#include "math/algebra.h"
#include <stdint.h>

#ifdef _WIN32
#pragma warning(push)
Expand Down Expand Up @@ -229,7 +231,10 @@ namespace indigo

struct LayoutOptions
{
static constexpr float DEFAULT_BOND_LENGTH = 1.6f;
// FIXME: The value is 1.6 instead of 1.0 due to backward compatibility, needs to be refactored
static constexpr float DEFAULT_BOND_LENGTH = 1.6f; // default length of inter-chemical bonds
static constexpr float DEFAULT_PLUS_SIZE = 1.0f;

float bondLength{DEFAULT_BOND_LENGTH};
UnitsOfMeasure::TYPE bondLengthUnit{UnitsOfMeasure::TYPE::PX};
float reactionComponentMarginSize{DEFAULT_BOND_LENGTH / 2};
Expand All @@ -240,7 +245,7 @@ namespace indigo
auto marginSizePt = UnitsOfMeasure::convertToPt(reactionComponentMarginSize, reactionComponentMarginSizeUnit, ppi);
auto bondLengthPt = UnitsOfMeasure::convertToPt(bondLength, bondLengthUnit, ppi);

return marginSizePt / bondLengthPt;
return (DEFAULT_BOND_LENGTH * marginSizePt) / bondLengthPt;
}
};

Expand Down
2 changes: 1 addition & 1 deletion core/indigo-core/layout/reaction_layout.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ namespace indigo
void processSideBoxes(std::vector<Vec2f>& pluses, Rect2f& type_box, int side);

const float bond_length;
const float atom_label_width;
const float atom_label_margin;
const float default_plus_size;
const float default_arrow_size;
const float reaction_margin_size;
Expand Down
5 changes: 4 additions & 1 deletion core/indigo-core/layout/src/metalayout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ Metalayout::LayoutLine& Metalayout::newLine()
void Metalayout::process()
{
Vec2f pos;
static const auto atomLabelMarginVertical = bondLength / 2;
for (int i = 0; i < _layout.size(); ++i)
{
LayoutLine& line = _layout[i];
Expand All @@ -95,12 +96,14 @@ void Metalayout::process()
{
LayoutItem& item = line.items[j];
Vec2f offset(pos);
auto shiftToAlignAboveVerticalCenter = line.top_height / 2;
switch (item.verticalAlign)
{
case LayoutItem::ItemVerticalAlign::ECenter:
break;
case LayoutItem::ItemVerticalAlign::ETop:
offset.y += reactionComponentMarginSize + line.top_height / 2;
// catalyst
offset.y += reactionComponentMarginSize + atomLabelMarginVertical + shiftToAlignAboveVerticalCenter;
break;
case LayoutItem::ItemVerticalAlign::EBottom:
offset.y -= (bondLength + line.bottom_height) / 2;
Expand Down
41 changes: 23 additions & 18 deletions core/indigo-core/layout/src/reaction_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,22 @@
#include <functional>
#include <numeric>
#include <stdio.h>
using namespace std::placeholders;

using namespace std::placeholders;
using namespace indigo;

ReactionLayout::ReactionLayout(BaseReaction& r, bool smart_layout)
: bond_length(LayoutOptions::DEFAULT_BOND_LENGTH), default_plus_size(1), default_arrow_size(2), preserve_molecule_layout(false), _r(r),
_smart_layout(smart_layout), reaction_margin_size(DEFAULT_HOR_INTERVAL_FACTOR), atom_label_width(1.3f), layout_orientation(UNCPECIFIED), max_iterations(0)
_smart_layout(smart_layout), reaction_margin_size(DEFAULT_HOR_INTERVAL_FACTOR), atom_label_margin(1.3f), layout_orientation(UNCPECIFIED),
max_iterations(0)
{
}

ReactionLayout::ReactionLayout(BaseReaction& r, bool smart_layout, const LayoutOptions& options)
: bond_length(LayoutOptions::DEFAULT_BOND_LENGTH), default_plus_size(1), default_arrow_size(LayoutOptions::DEFAULT_BOND_LENGTH * 2),
preserve_molecule_layout(false), _r(r), _smart_layout(smart_layout), reaction_margin_size(options.getMarginSizeInAngstroms()),
atom_label_width(LayoutOptions::DEFAULT_BOND_LENGTH / 2), layout_orientation(UNCPECIFIED), max_iterations(0)
: bond_length(LayoutOptions::DEFAULT_BOND_LENGTH), default_plus_size(LayoutOptions::DEFAULT_PLUS_SIZE),
default_arrow_size(LayoutOptions::DEFAULT_BOND_LENGTH * 2), preserve_molecule_layout(false), _r(r), _smart_layout(smart_layout),
reaction_margin_size(options.getMarginSizeInAngstroms()), atom_label_margin(LayoutOptions::DEFAULT_BOND_LENGTH / 2), layout_orientation(UNCPECIFIED),
max_iterations(0)
{
}

Expand Down Expand Up @@ -112,27 +114,27 @@ void ReactionLayout::_updateMetadata()
for (const auto& plus_offset : pluses)
_r.meta().addMetaObject(new KETReactionPlus(plus_offset));

// calculate arrow size and position
Vec2f arrow_head(0, 0);
Vec2f arrow_tail(0, 0);

if (_r.productsCount() == 0)
{
arrow_tail.x = react_box.right() + reaction_margin_size / 2;
arrow_tail.x = react_box.right() + reaction_margin_size + atom_label_margin;
arrow_tail.y = react_box.middleY();
arrow_head.x = arrow_tail.x + default_arrow_size;
arrow_head.x = arrow_tail.x + default_arrow_size + atom_label_margin;
arrow_head.y = arrow_tail.y;
}
else if (_r.reactantsCount() == 0)
{
arrow_head.x = product_box.left() - reaction_margin_size / 2;
arrow_head.x = product_box.left() - reaction_margin_size - atom_label_margin;
arrow_head.y = product_box.middleY();
arrow_tail.x = arrow_head.x - default_arrow_size;
arrow_tail.x = arrow_head.x - default_arrow_size - atom_label_margin;
arrow_tail.y = arrow_head.y;
}
else
{
const float ptab = first_single_product ? reaction_margin_size + bond_length / 2 : reaction_margin_size;
const float rtab = last_single_reactant ? reaction_margin_size + bond_length / 2 : reaction_margin_size;
const float ptab = /*first_single_product ? reaction_margin_size * 2 :*/ reaction_margin_size + atom_label_margin;
const float rtab = /*last_single_reactant ? reaction_margin_size * 2 :*/ reaction_margin_size + atom_label_margin;

arrow_head.y = product_box.middleY();
arrow_tail.y = react_box.middleY();
Expand Down Expand Up @@ -208,7 +210,10 @@ void ReactionLayout::make()
{
bool single_atom = _getMol(i).vertexCount() == 1;
if (i != begin)
_pushSpace(line, default_plus_size + reaction_margin_size * 2);
{
_pushSpace(line, reaction_margin_size);
_pushSpace(line, default_plus_size);
}
_pushMol(line, i);
}
};
Expand All @@ -217,6 +222,8 @@ void ReactionLayout::make()

if (_r.catalystCount())
{

_pushSpace(line, reaction_margin_size);
_pushSpace(line, reaction_margin_size);
for (int i = _r.catalystBegin(); i < _r.catalystEnd(); i = _r.catalystNext(i))
{
Expand All @@ -225,12 +232,10 @@ void ReactionLayout::make()
mol.getBoundingBox(bbox, Vec2f(bond_length, bond_length));
if (i != _r.catalystBegin())
_pushSpace(line, reaction_margin_size);
//_pushSpace(line, reaction_margin_size);
_pushMol(line, i, true);
//_pushSpace(line, reaction_margin_size);
//_pushSpace(line, reaction_margin_size / 2);
}
_pushSpace(line, reaction_margin_size);
_pushSpace(line, reaction_margin_size);
}
else
_pushSpace(line, default_arrow_size + reaction_margin_size * 2);
Expand All @@ -253,7 +258,7 @@ void ReactionLayout::_pushMol(Metalayout::LayoutLine& line, int id, bool is_cata
{
// Molecule label alligned to atom center by non-hydrogen
// Hydrogen may be at left or at right H2O, PH3 - so add space before and after molecule
_pushSpace(line, atom_label_width);
_pushSpace(line, atom_label_margin);
Metalayout::LayoutItem& item = line.items.push();
item.type = Metalayout::LayoutItem::Type::EMolecule;
item.isMoleculeFragment = true;
Expand All @@ -268,7 +273,7 @@ void ReactionLayout::_pushMol(Metalayout::LayoutLine& line, int id, bool is_cata
mol.getBoundingBox(bbox);
item.min.copy(bbox.leftBottom());
item.max.copy(bbox.rightTop());
_pushSpace(line, atom_label_width);
_pushSpace(line, atom_label_margin);
}

void ReactionLayout::_pushSpace(Metalayout::LayoutLine& line, float size)
Expand Down
1 change: 1 addition & 0 deletions core/indigo-core/reaction/reaction_json_saver.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <rapidjson/writer.h>

#include "base_cpp/exception.h"
#include "layout/metalayout.h"
#include "molecule/ket_commons.h"

namespace indigo
Expand Down
Loading

0 comments on commit a08e208

Please sign in to comment.