File: molecule_layout_graph.h

package info (click to toggle)
indigo 1.4.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 48,936 kB
  • sloc: ansic: 332,816; cpp: 169,470; python: 20,033; java: 13,701; cs: 9,979; asm: 8,475; sql: 6,743; xml: 6,354; javascript: 1,245; sh: 555; php: 506; makefile: 54
file content (703 lines) | stat: -rw-r--r-- 25,604 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
/****************************************************************************
 * Copyright (C) from 2009 to Present EPAM Systems.
 *
 * This file is part of Indigo toolkit.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ***************************************************************************/

#ifndef __molecule_layout_graph_h__
#define __molecule_layout_graph_h__

#include "base_cpp/cancellation_handler.h"
#include "base_cpp/obj.h"
#include "base_cpp/obj_array.h"
#include "base_cpp/tlscont.h"
#include "graph/filter.h"
#include "graph/graph.h"
#include "layout/layout_pattern.h"
#include "math/algebra.h"
#include "molecule/molecule.h"

#ifdef _WIN32
#pragma warning(push)
#pragma warning(disable : 4251)
#endif

namespace indigo
{

    const int SOME_MAGIC_INT_FOR_RANDOM_1 = 931170243;
    const int SOME_MAGIC_INT_FOR_RANDOM_2 = 931170240;
    const int SOME_MAGIC_INT_FOR_RANDOM_3 = 931170242;
    const int SOME_MAGIC_INT_FOR_RANDOM_4 = 931170241;

    class BiconnectedDecomposer;

#ifdef _DEBUG
#define M_LAYOUT_DEBUG
#endif

    enum
    {
        ELEMENT_NOT_DRAWN = 0,
        ELEMENT_INTERNAL,
        ELEMENT_BOUNDARY,
        ELEMENT_NOT_PLANAR,
        ELEMENT_IGNORE,
        ELEMENT_DRAWN
    };

    struct LayoutVertex
    {
        LayoutVertex()
        {
            memset(this, 0, sizeof(LayoutVertex));
        }

        int ext_idx;
        int orig_idx;
        long morgan_code;
        bool is_cyclic;
        int type;

        Vec2f pos;
    };

    struct LayoutEdge
    {
        LayoutEdge()
        {
            memset(this, 0, sizeof(LayoutEdge));
        }

        int ext_idx;
        int orig_idx;
        bool is_cyclic;
        int type;
    };

    class DLLEXPORT MoleculeLayoutGraph : public Graph
    {
    public:
        explicit MoleculeLayoutGraph();
        virtual ~MoleculeLayoutGraph();

        virtual MoleculeLayoutGraph* getInstance() = 0;

        inline const Vec2f& getPos(int idx) const
        {
            return _layout_vertices[idx].pos;
        }
        inline Vec2f& getPos(int idx)
        {
            return _layout_vertices[idx].pos;
        }
        inline int getVertexExtIdx(int idx) const
        {
            return _layout_vertices[idx].ext_idx;
        }
        inline int getVertexType(int idx) const
        {
            return _layout_vertices[idx].type;
        }
        inline int getEdgeExtIdx(int idx) const
        {
            return _layout_edges[idx].ext_idx;
        }
        inline int getEdgeType(int idx) const
        {
            return _layout_edges[idx].type;
        }

        void setVertexType(int idx, int type)
        {
            _layout_vertices[idx].type = type;
        }
        void setEdgeType(int idx, int type)
        {
            _layout_edges[idx].type = type;
        }

        virtual void clear();

        bool isSingleEdge() const;

        void registerLayoutVertex(int idx, const LayoutVertex& vertex);
        void registerLayoutEdge(int idx, const LayoutEdge& edge);
        int addLayoutVertex(int ext_idx, int type);
        int addLayoutEdge(int beg, int end, int ext_idx, int type);

        const LayoutVertex& getLayoutVertex(int idx) const;
        const LayoutEdge& getLayoutEdge(int idx) const;

        int findVertexByExtIdx(int ext_idx) const;

        virtual float calculateAngle(int v, int& v1, int& v2) const = 0;

        void makeOnGraph(Graph& graph);
        virtual void makeLayoutSubgraph(MoleculeLayoutGraph& graph, Filter& filter) = 0;
        void cloneLayoutGraph(MoleculeLayoutGraph& other, Array<int>* mapping);
        void copyLayoutTo(MoleculeLayoutGraph& other, const Array<int>& mapping) const;

        virtual void layout(BaseMolecule& molecule, float bond_length, const Filter* filter, bool respect_existing) = 0;

        const BaseMolecule* getMolecule(const int** molecule_edge_mapping)
        {
            *molecule_edge_mapping = _molecule_edge_mapping;
            return _molecule;
        }

        virtual void flipped() = 0;
        bool isFlipped() const
        {
            return _flipped;
        }

        bool _flipped; // component was flipped after attaching

        int max_iterations;
        layout_orientation_value layout_orientation;

        CancellationHandler* cancellation;

        DECL_ERROR;

        ObjArray<LayoutVertex> _layout_vertices;
        ObjArray<LayoutEdge> _layout_edges;

        Array<int> _fixed_vertices;

        long _total_morgan_code;
        int _first_vertex_idx;
        int _n_fixed;

        // Outline of the graph (from pattern)
        Obj<Array<Vec2f>> _outline;

        BaseMolecule* _molecule;
        const int* _molecule_edge_mapping;

        struct Cycle
        {
            explicit Cycle();
            explicit Cycle(const List<int>& edges, const MoleculeLayoutGraph& graph);
            explicit Cycle(const Array<int>& vertices, const Array<int>& edges);

            void copy(const List<int>& edges, const MoleculeLayoutGraph& graph);
            void copy(const Array<int>& vertices, const Array<int>& edges);

            int vertexCount() const
            {
                return _vertices.size();
            }
            int getVertex(int idx) const
            {
                return _vertices[idx];
            }
            int getVertexC(int idx) const
            {
                return _vertices[(vertexCount() + idx) % vertexCount()];
            }
            int getEdge(int idx) const
            {
                return _edges[idx];
            }
            int getEdgeC(int idx) const
            {
                return _edges[(_edges.size() + idx) % _edges.size()];
            }
            int getEdgeStart(int idx) const
            {
                return getVertexC(idx);
            }
            int getEdgeFinish(int idx) const
            {
                return getVertexC(idx + 1);
            }
            int findVertex(int idx) const
            {
                return _vertices.find(idx);
            }
            long morganCode() const
            {
                if (!_morgan_code_calculated)
                    throw Error("Morgan code does not calculated yet.");
                return _morgan_code;
            }
            void setVertexWeight(int idx, int w)
            {
                _attached_weight[idx] = w;
            }
            void addVertexWeight(int idx, int w)
            {
                _attached_weight[idx] += w;
            }
            int getVertexWeight(int idx) const
            {
                return _attached_weight[idx];
            }
            void canonize();
            bool contains(const Cycle& another) const;
            void calcMorganCode(const MoleculeLayoutGraph& parent_graph);

            static int compare_cb(int& idx1, int& idx2, void* context);

        protected:
            CP_DECL;
            TL_CP_DECL(Array<int>, _vertices);
            TL_CP_DECL(Array<int>, _edges);
            TL_CP_DECL(Array<int>, _attached_weight);

            int _max_idx;
            long _morgan_code;
            bool _morgan_code_calculated;

        private:
            Cycle(const Cycle& other); // No copy constructor
        };
        struct EnumContext
        {
            const MoleculeLayoutGraph* graph;
            RedBlackSet<int>* edges;
            int iterationNumber;
            int maxIterationNumber;
        };

        // geometry functions
        int _calcIntersection(int edge1, int edge2) const;
        bool _isVertexOnEdge(int vert_idx, int edge_beg, int edge_end) const;
        bool _isVertexOnSomeEdge(int vert_idx) const;
        void _shiftEdge(int edge_idx, float delta);
        bool _drawRegularCurve(const Array<int>& chain, int begin, int end, float length, bool ccw, int type);
        bool _drawRegularCurveEx(const Array<int>& chain, int begin, int end, float length, bool ccw, int type, const Array<int>& mapping);
        static void _findAngles(int k, float s, float& x, float& y);
        static float _dichotomy1(float a0, float b0, int L, float s);
        static float _dichotomy2(float a0, float b0, int L, float s);
        static void _calculatePos(float phi, const Vec2f& v1, const Vec2f& v2, Vec2f& v);

        // border functions
        virtual void _getBorder(Cycle& border) const = 0;
        virtual bool _isPointOutside(const Vec2f& p) const = 0;
        virtual bool _isPointOutsideCycle(const Cycle& cycle, const Vec2f& p) const = 0;
        bool _isPointOutsideCycleEx(const Cycle& cycle, const Vec2f& p, const Array<int>& mapping) const;
        static bool _border_cb(Graph& graph, const Array<int>& vertices, const Array<int>& edges, void* context);

        // for components
        virtual void _calcMorganCodes() = 0;

        // for whole graph
        virtual void _assignAbsoluteCoordinates(float bond_length) = 0;

        bool _checkBadTryBorderIntersection(Array<int>& chain_ext, MoleculeLayoutGraph& next_bc, Array<int>& mapping);
        bool _checkBadTryChainOutside(Array<int>& chain_ext, MoleculeLayoutGraph& next_bc, Array<int>& mapping);

        virtual void _assignRelativeCoordinates(int& fixed_component, const MoleculeLayoutGraph& supergraph) = 0;

        // refine
        static bool _edge_check(Graph& graph, int e_idx, void* context);
        void _refineCoordinates(const BiconnectedDecomposer& bc_decomposer, const PtrArray<MoleculeLayoutGraph>& bc_components, const Array<int>& bc_tree);
        bool _allowRotateAroundVertex(int idx) const;
        void _makeBranches(Array<int>& branches, int edge, Filter& filter) const;
        void _excludeDandlingIntersections();
        static bool _path_handle(Graph& graph, const Array<int>& vertices, const Array<int>& edges, void* context);

        // attaching
        void _attachEars(int vert_idx, int drawn_idx, int* ears, const Vec2f& rest_pos);

        // assigning coordinates
        void _attachDandlingVertices(int vert_idx, Array<int>& adjacent_list);
        void _calculatePositionsOneNotDrawn(Array<Vec2f>& positions, int n_pos, int vert_idx, int not_drawn_idx);
        void _calculatePositionsSingleDrawn(int vert_idx, Array<int>& adjacent_list, int& n_pos, int drawn_idx, bool& two_ears, Array<Vec2f>& positions,
                                            int& parity);
        void _orderByEnergy(Array<Vec2f>& positions);
        void _assignRelativeSingleEdge(int& fixed_component, const MoleculeLayoutGraph& supergraph);
        void _findFirstVertexIdx(int n_comp, Array<int>& fixed_components, PtrArray<MoleculeLayoutGraph>& bc_components, bool all_trivial);
        bool _prepareAssignedList(Array<int>& assigned_list, BiconnectedDecomposer& bc_decom, PtrArray<MoleculeLayoutGraph>& bc_components,
                                  Array<int>& bc_tree);
        void _assignFinalCoordinates(float bond_length, const Array<Vec2f>& src_layout);
        void _copyLayout(MoleculeLayoutGraph& component);
        void _getAnchor(int& v1, int& v2, int& v3) const;

        void _findFixedComponents(BiconnectedDecomposer& bc_decom, Array<int>& fixed_components, PtrArray<MoleculeLayoutGraph>& bc_components);
        bool _assignComponentsRelativeCoordinates(PtrArray<MoleculeLayoutGraph>& bc_components, Array<int>& fixed_components, BiconnectedDecomposer& bc_decom);
        void _attachCrossingEdges();

        void _buildOutline(void);
    };

    class DLLEXPORT MoleculeLayoutGraphSimple : public MoleculeLayoutGraph
    {
    public:
        explicit MoleculeLayoutGraphSimple();
        virtual ~MoleculeLayoutGraphSimple();

        MoleculeLayoutGraph* getInstance();

        virtual void clear();

        float calculateAngle(int v, int& v1, int& v2) const;

        void makeLayoutSubgraph(MoleculeLayoutGraph& graph, Filter& filter);

        void layout(BaseMolecule& molecule, float bond_length, const Filter* filter, bool respect_existing);

        void flipped()
        {
            _flipped = true;
        };

#ifdef M_LAYOUT_DEBUG
        void saveDebug();
#endif

        DECL_ERROR;

    protected:
        // patterns
        void _initPatterns();
        static int _pattern_cmp(PatternLayout& p1, PatternLayout& p2, void* context);
        static int _pattern_cmp2(PatternLayout& p1, int n_v, int n_e, long code);
        static bool _match_pattern_bond(Graph& subgraph, Graph& supergraph, int self_idx, int other_idx, void* userdata);
        static int _pattern_embedding(Graph& subgraph, Graph& supergraph, int* core_sub, int* core_super, void* userdata);

        // THERE

        // for whole graph
        void _assignAbsoluteCoordinates(float bond_length);

        // for components
        void _calcMorganCodes();

        // assigning coordinates
        void _assignRelativeCoordinates(int& fixed_component, const MoleculeLayoutGraph& supergraph);
        bool _tryToFindPattern(int& fixed_component);
        void _assignFirstCycle(const Cycle& cycle);

        // attaching cycles
        bool _attachCycleOutside(const Cycle& cycle, float length, int n_common);
        bool _drawEdgesWithoutIntersection(const Cycle& cycle, Array<int>& cycle_vertex_types);

        bool _attachCycleInside(const Cycle& cycle, float length);
        bool _attachCycleWithIntersections(const Cycle& cycle, float length);
        void _setChainType(const Array<int>& chain, const Array<int>& mapping, int type);
        bool _splitCycle(const Cycle& cycle, const Array<int>& cycle_vertex_types, bool check_boundary, Array<int>& chain_ext, Array<int>& chain_int,
                         int& c_beg, int& c_end) const;
        void _splitCycle2(const Cycle& cycle, const Array<int>& cycle_vertex_types, ObjArray<Array<int>>& chains_ext) const;

        // border functions
        void _getBorder(Cycle& border) const;
        void _splitBorder(int v1, int v2, Array<int>& part1v, Array<int>& part1e, Array<int>& part2v, Array<int>& part2e) const;
        bool _isPointOutside(const Vec2f& p) const;
        bool _isPointOutsideCycle(const Cycle& cycle, const Vec2f& p) const;

        static bool _edge_check(Graph& graph, int e_idx, void* context);

        // make tree of biconnected components (tree[i] - component incoming to vertex i or -1)
        static void _makeComponentsTree(BiconnectedDecomposer& decon, PtrArray<MoleculeLayoutGraph>& components, Array<int>& tree);

        void _layoutMultipleComponents(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);
        void _layoutSingleComponent(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);

        TL_DECL(ObjArray<PatternLayout>, _patterns);
    };

    struct local_pair_ii
    {
        int left;
        int right;

        local_pair_ii(int l, int r)
        {
            left = l;
            right = r;
        }
    };

    struct local_pair_id
    {
        int left;
        float right;

        local_pair_id(int l, float r)
        {
            left = l;
            right = r;
        }
    };

    class MoleculeLayoutGraphSmart;
    class MoleculeLayoutMacrocycles;
    class MoleculeLayoutMacrocyclesLattice;

    class DLLEXPORT MoleculeLayoutSmoothingSegment
    {

    private:
        float _length;
        Array<Vec2f> _pos;
        int _finish_number;
        int _start_number;
        Vec2f& _start;
        Vec2f& _finish;
        Vec2f _center;
        int _layout_component_number;
        float _square;
        float _radius;

        Vec2f _getPosition(Vec2f);
        float calc_radius(Vec2f);

    public:
        MoleculeLayoutGraphSmart& _graph;

        MoleculeLayoutSmoothingSegment(MoleculeLayoutGraphSmart& mol, Vec2f& start, Vec2f& finish);
        Vec2f getPosition(int);
        Vec2f getIntPosition(int) const;
        void shiftStartBy(Vec2f shift);
        void shiftFinishBy(Vec2f shift);
        float getLength() const;
        float getLengthCoef() const;
        Vec2f getCenter();
        Vec2f getIntCenter();
        void updateStartFinish();
        bool isVertexUp(int v);
        int get_layout_component_number();
        void set_layout_component_number(int number);
        void inverse();
        void set_start_finish_number(int, int);
        float get_square();
        void calculate_square();
        int get_start() const;
        int get_finish() const;
        float get_radius();
        bool can_touch_to(MoleculeLayoutSmoothingSegment&);

        bool is_start(int v)
        {
            return v == _start_number;
        }
        bool is_finish(int v)
        {
            return v == _finish_number;
        }

        float get_min_x();
        float get_min_y();
        float get_max_x();
        float get_max_y();
    };

    class DLLEXPORT SmoothingCycle
    {
    public:
        CP_DECL;
        SmoothingCycle(Array<Vec2f>&, Array<float>&);
        SmoothingCycle(Array<Vec2f>&, Array<float>&, Array<int>&, int);
        SmoothingCycle(Array<Vec2f>&, Array<float>&, ObjArray<MoleculeLayoutSmoothingSegment>&);

        int cycle_length;
        Array<Vec2f>& point;
        Array<float>& target_angle;
        MoleculeLayoutSmoothingSegment* segment;
        TL_CP_DECL(Array<float>, edge_length);

        bool is_simple_component(int i)
        {
            return segment == 0 || segment[i].get_layout_component_number() < 0;
        }
        float get_radius(int i)
        {
            return segment == 0 ? (point[(i + 1) % cycle_length] - point[i]).length() / 2 : segment[i].get_radius();
        }
        Vec2f get_center(int i)
        {
            return segment == 0 ? (point[(i + 1) % cycle_length] + point[i]) / 2 : segment[i].getCenter();
        }
        float get_length(int i)
        {
            return edge_length[i];
        }

        DECL_ERROR;

        void _do_smoothing(int iter_count);

        void _gradient_step(float coef, Array<local_pair_ii>& touching_segments, bool);

        static Vec2f _get_len_derivative(Vec2f current_vector, float target_dist, bool);
        static Vec2f _get_len_derivative_simple(Vec2f current_vector, float target_dist);
        static Vec2f _get_angle_derivative(Vec2f left_point, Vec2f right_point, float target_angle, bool flag = false);
    };

    class DLLEXPORT MoleculeLayoutGraphSmart : public MoleculeLayoutGraph
    {
    public:
        explicit MoleculeLayoutGraphSmart();
        virtual ~MoleculeLayoutGraphSmart();

        MoleculeLayoutGraph* getInstance();

        virtual void clear();

        inline int getVertexOrigIdx(int idx) const
        {
            return _layout_vertices[idx].orig_idx;
        }
        inline int getEdgeOrigIdx(int idx) const
        {
            return _layout_edges[idx].orig_idx;
        }
        inline bool isEdgeDrawn(int idx) const
        {
            return _layout_edges[idx].type != ELEMENT_NOT_DRAWN;
        }
        inline bool isVertexDrawn(int idx) const
        {
            return _layout_vertices[idx].type != ELEMENT_NOT_DRAWN;
        }

        float calculateAngle(int v, int& v1, int& v2) const;

        void makeLayoutSubgraph(MoleculeLayoutGraph& graph, Filter& vertex_filter);
        void makeLayoutSubgraph(MoleculeLayoutGraph& graph, Filter& vertex_filter, Filter* edge_filter);
        void layout(BaseMolecule& molecule, float bond_length, const Filter* filter, bool respect_existing);

        void calcMorganCode();
        long getMorganCode();

        void assignFirstVertex(int v);

        const BaseMolecule* getMolecule(const int** molecule_edge_mapping)
        {
            *molecule_edge_mapping = _molecule_edge_mapping;
            return _molecule;
        }
        const BaseMolecule* getMolecule()
        {
            return _molecule;
        }

        const int* getEdgeMapping()
        {
            return _molecule_edge_mapping;
        }

        float _get_square();
        void flipped()
        {
            ;
        }

#ifdef M_LAYOUT_DEBUG
        void saveDebug();
#endif

        DECL_ERROR;

    protected:
        // THERE

        // for whole graph
        void _assignAbsoluteCoordinates(float bond_length);

        // for components
        void _calcMorganCodes();

        // assigning coordinates
        struct interval
        {
            int left;
            int right;

            void init(int _l, int _r)
            {
                left = _l;
                right = _r;
            }
            interval(int _l, int _r)
            {
                init(_l, _r);
            }
        };

        void _assignRelativeCoordinates(int& fixed_component, const MoleculeLayoutGraph& supergraph);
        void _get_toches_to_component(Cycle& cycle, int component_number, Array<interval>& interval_list);
        int _search_separated_component(Cycle& cycle, Array<interval>& interval_list);
        void _search_path(int start, int finish, Array<int>& path, int component_number);
        void _assignEveryCycle(const Cycle& cycle);

        // smoothing
        void _segment_smoothing(const Cycle& cycle, const MoleculeLayoutMacrocyclesLattice& layout, Array<int>& rotation_vertex, Array<Vec2f>& rotation_point,
                                ObjArray<MoleculeLayoutSmoothingSegment>& segment);
        void _update_touching_segments(Array<local_pair_ii>&, ObjArray<MoleculeLayoutSmoothingSegment>&);
        void _segment_smoothing_prepearing(const Cycle& cycle, Array<int>& rotation_vertex, Array<Vec2f>& rotation_point,
                                           ObjArray<MoleculeLayoutSmoothingSegment>& segment, MoleculeLayoutMacrocyclesLattice& layout);
        void _segment_calculate_target_angle(const MoleculeLayoutMacrocyclesLattice& layout, Array<int>& rotation_vertex, Array<float>& target_angle,
                                             ObjArray<MoleculeLayoutSmoothingSegment>& segment);
        void _segment_update_rotation_points(const Cycle& cycle, Array<int>& rotation_vertex, Array<Vec2f>& rotation_point,
                                             ObjArray<MoleculeLayoutSmoothingSegment>& segment);
        void _segment_smoothing_unstick(ObjArray<MoleculeLayoutSmoothingSegment>& segment);
        void _do_segment_smoothing(Array<Vec2f>& rotation_point, Array<float>& target_angle, ObjArray<MoleculeLayoutSmoothingSegment>& segment);
        void _segment_improoving(Array<Vec2f>& rotation_point, Array<float>& target_angle, ObjArray<MoleculeLayoutSmoothingSegment>& segment, int, float,
                                 Array<local_pair_ii>&);
        void _do_segment_smoothing_gradient(Array<Vec2f>& rotation_point, Array<float>& target_angle, ObjArray<MoleculeLayoutSmoothingSegment>& segment);
        void _gradient_step(Array<Vec2f>& point, Array<float>& target_angle, ObjArray<MoleculeLayoutSmoothingSegment>& segment, float coef,
                            Array<local_pair_ii>& touching_segments);

        void _attachEars(int vert_idx, int drawn_idx, int* ears, const Vec2f& rest_pos);

        // attaching cycles
        bool _attachCycleOutside(const Cycle& cycle, float length, int n_common);
        bool _drawEdgesWithoutIntersection(const Cycle& cycle, Array<int>& cycle_vertex_types);

        bool _attachCycleInside(const Cycle& cycle, float length);
        bool _attachCycleWithIntersections(const Cycle& cycle, float length);
        void _setChainType(const Array<int>& chain, const Array<int>& mapping, int type);
        bool _splitCycle(const Cycle& cycle, const Array<int>& cycle_vertex_types, bool check_boundary, Array<int>& chain_ext, Array<int>& chain_int,
                         int& c_beg, int& c_end) const;
        void _splitCycle2(const Cycle& cycle, const Array<int>& cycle_vertex_types, ObjArray<Array<int>>& chains_ext) const;

        // border functions
        void _getBorder(Cycle& border) const;
        void _getSurroundCycle(Cycle& cycle, Vec2f p) const;
        void _splitBorder(int v1, int v2, Array<int>& part1v, Array<int>& part1e, Array<int>& part2v, Array<int>& part2e) const;
        bool _isPointOutside(const Vec2f& p) const;
        bool _isPointOutsideCycle(const Cycle& cycle, const Vec2f& p) const;

        // geometry functions
        const float _energyOfPoint(Vec2f p) const;
        int _isCisConfiguratuin(Vec2f p1, Vec2f p2, Vec2f p3, Vec2f p4);

        // make tree of biconnected components (tree[i] - -1 or component incoming to vertex i)
        static void _makeComponentsTree(BiconnectedDecomposer& decon, PtrArray<MoleculeLayoutGraph>& components, Array<int>& tree);

        void _layoutMultipleComponents(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);
        void _layoutSingleComponent(BaseMolecule& molecule, bool respect_existing, const Filter* filter, float bond_length);

        Array<int> _layout_component_number; // number of layout component of certain edge
        int _layout_component_count;

        MoleculeLayoutGraph* _graph;

    private:
        MoleculeLayoutGraphSmart(const MoleculeLayoutGraphSmart&);
    };

} // namespace indigo

#ifdef _WIN32
#pragma warning(pop)
#endif

#endif