0026917: 3D Offset algorithm produces incorrect result
authoremv <emv@opencascade.com>
Tue, 8 Nov 2016 15:04:28 +0000 (18:04 +0300)
committerapn <apn@opencascade.com>
Tue, 8 Nov 2016 15:05:05 +0000 (18:05 +0300)
Extension on the 3D Offset algorithm (Mode="Complete", Join Type = "Intersection")
for colliding cases to add support for new configurations of the shapes.
In the previous approach the result of the offset operation was build from
the offset faces using MakerVolume algorithm, without checking of the validity of these faces.
The new extension is based on this approach, but now the offset faces are being checked
on invalidity and rebuild in case of any. This allows (in case of successful rebuilding) to avoid creation
of the unforeseen parts such as dangling parts, spikes, inverted faces in the result of offset operation.
The main criteria for the validity of the faces is the coincidence of the normal
direction of the offset face with the normal direction of the original face.
Check for removal of invalid faces has been removed as obsolete.

BRepOffset_Inter2D: Avoid excess trimming of the edges due to coincidence with other edges.
BRepOffset_Inter3D: Careful treatment of the intersection of the faces connected only through vertices.

Eliminating the compiler warning.

Small corrections of test cases for issue CR26917

572 files changed:
src/BOPAlgo/BOPAlgo_Builder_4.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx
src/BOPTools/BOPTools_AlgoTools_2.cxx
src/BRepOffset/BRepOffset_Inter2d.cxx
src/BRepOffset/BRepOffset_Inter2d.hxx
src/BRepOffset/BRepOffset_Inter3d.cxx
src/BRepOffset/BRepOffset_MakeOffset.cxx
src/BRepOffset/BRepOffset_MakeOffset.hxx
src/BRepOffset/BRepOffset_MakeOffset_1.cxx [new file with mode: 0644]
src/BRepOffset/FILES
src/BRepTest/BRepTest_FeatureCommands.cxx
tests/bugs/modalg_6/bug27540_1
tests/bugs/modalg_6/bug27540_2
tests/bugs/modalg_6/bug27540_3
tests/offset/end
tests/offset/shape_type_i_c/A1
tests/offset/shape_type_i_c/A2
tests/offset/shape_type_i_c/A3
tests/offset/shape_type_i_c/A4
tests/offset/shape_type_i_c/A5
tests/offset/shape_type_i_c/A6
tests/offset/shape_type_i_c/A7
tests/offset/shape_type_i_c/A8
tests/offset/shape_type_i_c/A9
tests/offset/shape_type_i_c/B1
tests/offset/shape_type_i_c/B2
tests/offset/shape_type_i_c/B3
tests/offset/shape_type_i_c/B4
tests/offset/shape_type_i_c/B5
tests/offset/shape_type_i_c/B6
tests/offset/shape_type_i_c/B7
tests/offset/shape_type_i_c/B8
tests/offset/shape_type_i_c/B9
tests/offset/shape_type_i_c/C1
tests/offset/shape_type_i_c/C2
tests/offset/shape_type_i_c/C3
tests/offset/shape_type_i_c/C4
tests/offset/shape_type_i_c/C5
tests/offset/shape_type_i_c/C6
tests/offset/shape_type_i_c/C7
tests/offset/shape_type_i_c/C8
tests/offset/shape_type_i_c/C9
tests/offset/shape_type_i_c/D1
tests/offset/shape_type_i_c/D2
tests/offset/shape_type_i_c/D3
tests/offset/shape_type_i_c/D4
tests/offset/shape_type_i_c/D5
tests/offset/shape_type_i_c/D6
tests/offset/shape_type_i_c/D7
tests/offset/shape_type_i_c/D8
tests/offset/shape_type_i_c/D9
tests/offset/shape_type_i_c/E1
tests/offset/shape_type_i_c/E2
tests/offset/shape_type_i_c/E3
tests/offset/shape_type_i_c/E4
tests/offset/shape_type_i_c/E5
tests/offset/shape_type_i_c/E6
tests/offset/shape_type_i_c/E7
tests/offset/shape_type_i_c/E8
tests/offset/shape_type_i_c/E9
tests/offset/shape_type_i_c/F1
tests/offset/shape_type_i_c/F2
tests/offset/shape_type_i_c/F3
tests/offset/shape_type_i_c/F4
tests/offset/shape_type_i_c/F5
tests/offset/shape_type_i_c/F6
tests/offset/shape_type_i_c/F7
tests/offset/shape_type_i_c/F8
tests/offset/shape_type_i_c/F9
tests/offset/shape_type_i_c/G1
tests/offset/shape_type_i_c/G2
tests/offset/shape_type_i_c/G3
tests/offset/shape_type_i_c/G4
tests/offset/shape_type_i_c/G5
tests/offset/shape_type_i_c/G6
tests/offset/shape_type_i_c/G7
tests/offset/shape_type_i_c/G8
tests/offset/shape_type_i_c/G9
tests/offset/shape_type_i_c/H1
tests/offset/shape_type_i_c/H2
tests/offset/shape_type_i_c/H3
tests/offset/shape_type_i_c/H4
tests/offset/shape_type_i_c/H5
tests/offset/shape_type_i_c/H6
tests/offset/shape_type_i_c/H7
tests/offset/shape_type_i_c/H8
tests/offset/shape_type_i_c/H9
tests/offset/shape_type_i_c/I1
tests/offset/shape_type_i_c/I2
tests/offset/shape_type_i_c/I3
tests/offset/shape_type_i_c/I4
tests/offset/shape_type_i_c/I5
tests/offset/shape_type_i_c/I6
tests/offset/shape_type_i_c/I7
tests/offset/shape_type_i_c/I8
tests/offset/shape_type_i_c/I9
tests/offset/shape_type_i_c/J1 [new file with mode: 0644]
tests/offset/shape_type_i_c/J2
tests/offset/shape_type_i_c/J3
tests/offset/shape_type_i_c/J4
tests/offset/shape_type_i_c/J5
tests/offset/shape_type_i_c/J6
tests/offset/shape_type_i_c/J7
tests/offset/shape_type_i_c/J8
tests/offset/shape_type_i_c/J9
tests/offset/shape_type_i_c/K1
tests/offset/shape_type_i_c/K2
tests/offset/shape_type_i_c/K3
tests/offset/shape_type_i_c/K4
tests/offset/shape_type_i_c/K5
tests/offset/shape_type_i_c/K6
tests/offset/shape_type_i_c/K7
tests/offset/shape_type_i_c/K8
tests/offset/shape_type_i_c/K9
tests/offset/shape_type_i_c/L1
tests/offset/shape_type_i_c/L2
tests/offset/shape_type_i_c/L3
tests/offset/shape_type_i_c/L4
tests/offset/shape_type_i_c/L5
tests/offset/shape_type_i_c/L6
tests/offset/shape_type_i_c/L7
tests/offset/shape_type_i_c/L8
tests/offset/shape_type_i_c/L9
tests/offset/shape_type_i_c/M1
tests/offset/shape_type_i_c/M2
tests/offset/shape_type_i_c/M3
tests/offset/shape_type_i_c/M4
tests/offset/shape_type_i_c/M5
tests/offset/shape_type_i_c/M6
tests/offset/shape_type_i_c/M7
tests/offset/shape_type_i_c/M8
tests/offset/shape_type_i_c/M9
tests/offset/shape_type_i_c/N1
tests/offset/shape_type_i_c/N2
tests/offset/shape_type_i_c/N3
tests/offset/shape_type_i_c/N4
tests/offset/shape_type_i_c/N5
tests/offset/shape_type_i_c/N6
tests/offset/shape_type_i_c/N7
tests/offset/shape_type_i_c/N8
tests/offset/shape_type_i_c/N9
tests/offset/shape_type_i_c/O1
tests/offset/shape_type_i_c/O2
tests/offset/shape_type_i_c/O3
tests/offset/shape_type_i_c/O4
tests/offset/shape_type_i_c/O5
tests/offset/shape_type_i_c/O6
tests/offset/shape_type_i_c/O7
tests/offset/shape_type_i_c/O8
tests/offset/shape_type_i_c/O9
tests/offset/shape_type_i_c/P1
tests/offset/shape_type_i_c/P2
tests/offset/shape_type_i_c/P3
tests/offset/shape_type_i_c/P4
tests/offset/shape_type_i_c/P5
tests/offset/shape_type_i_c/P6
tests/offset/shape_type_i_c/P7
tests/offset/shape_type_i_c/P8 [new file with mode: 0644]
tests/offset/shape_type_i_c/P9 [new file with mode: 0644]
tests/offset/shape_type_i_c/Q1 [new file with mode: 0644]
tests/offset/shape_type_i_c/Q2 [new file with mode: 0644]
tests/offset/shape_type_i_c/Q3 [new file with mode: 0644]
tests/offset/shape_type_i_c/Q4 [new file with mode: 0644]
tests/offset/shape_type_i_c/Q5 [new file with mode: 0644]
tests/offset/shape_type_i_c/Q6 [new file with mode: 0644]
tests/offset/shape_type_i_c/Q7 [new file with mode: 0644]
tests/offset/shape_type_i_c/Q8 [new file with mode: 0644]
tests/offset/shape_type_i_c/Q9 [new file with mode: 0755]
tests/offset/shape_type_i_c/R1 [new file with mode: 0644]
tests/offset/shape_type_i_c/R2 [new file with mode: 0644]
tests/offset/shape_type_i_c/R3 [new file with mode: 0644]
tests/offset/shape_type_i_c/R4 [new file with mode: 0644]
tests/offset/shape_type_i_c/R5 [new file with mode: 0644]
tests/offset/shape_type_i_c/R6 [new file with mode: 0644]
tests/offset/shape_type_i_c/R7 [new file with mode: 0644]
tests/offset/shape_type_i_c/R8 [new file with mode: 0644]
tests/offset/shape_type_i_c/R9 [new file with mode: 0644]
tests/offset/shape_type_i_c/S1 [new file with mode: 0644]
tests/offset/shape_type_i_c/S2 [new file with mode: 0644]
tests/offset/shape_type_i_c/S3 [new file with mode: 0644]
tests/offset/shape_type_i_c/S4 [new file with mode: 0644]
tests/offset/shape_type_i_c/S5 [new file with mode: 0644]
tests/offset/shape_type_i_c/S6 [new file with mode: 0644]
tests/offset/shape_type_i_c/S7 [new file with mode: 0644]
tests/offset/shape_type_i_c/S8 [new file with mode: 0644]
tests/offset/shape_type_i_c/S9 [new file with mode: 0644]
tests/offset/shape_type_i_c/T1 [new file with mode: 0644]
tests/offset/shape_type_i_c/T2 [new file with mode: 0644]
tests/offset/shape_type_i_c/T3 [new file with mode: 0644]
tests/offset/shape_type_i_c/T4 [new file with mode: 0644]
tests/offset/shape_type_i_c/T5 [new file with mode: 0644]
tests/offset/shape_type_i_c/T6 [new file with mode: 0644]
tests/offset/shape_type_i_c/T7 [new file with mode: 0644]
tests/offset/shape_type_i_c/T8 [new file with mode: 0644]
tests/offset/shape_type_i_c/T9 [new file with mode: 0644]
tests/offset/shape_type_i_c/U1 [new file with mode: 0644]
tests/offset/shape_type_i_c/U2 [new file with mode: 0644]
tests/offset/shape_type_i_c/U3 [new file with mode: 0644]
tests/offset/shape_type_i_c/U4 [new file with mode: 0644]
tests/offset/shape_type_i_c/U5 [new file with mode: 0644]
tests/offset/shape_type_i_c/U6 [new file with mode: 0755]
tests/offset/shape_type_i_c/U7 [new file with mode: 0644]
tests/offset/shape_type_i_c/U8 [new file with mode: 0644]
tests/offset/shape_type_i_c/U9 [new file with mode: 0644]
tests/offset/shape_type_i_c/V1 [new file with mode: 0644]
tests/offset/shape_type_i_c/V2 [new file with mode: 0644]
tests/offset/shape_type_i_c/V3 [new file with mode: 0644]
tests/offset/shape_type_i_c/V4 [new file with mode: 0644]
tests/offset/shape_type_i_c/V5 [new file with mode: 0644]
tests/offset/shape_type_i_c/V6 [new file with mode: 0644]
tests/offset/shape_type_i_c/V7 [new file with mode: 0644]
tests/offset/shape_type_i_c/V8 [new file with mode: 0644]
tests/offset/shape_type_i_c/V9 [new file with mode: 0644]
tests/offset/shape_type_i_c/W1 [new file with mode: 0644]
tests/offset/shape_type_i_c/W2 [new file with mode: 0644]
tests/offset/shape_type_i_c/W3 [new file with mode: 0644]
tests/offset/shape_type_i_c/W4 [new file with mode: 0644]
tests/offset/shape_type_i_c/W5 [new file with mode: 0644]
tests/offset/shape_type_i_c/W6 [new file with mode: 0644]
tests/offset/shape_type_i_c/W7 [new file with mode: 0644]
tests/offset/shape_type_i_c/W8 [new file with mode: 0644]
tests/offset/shape_type_i_c/W9 [new file with mode: 0644]
tests/offset/shape_type_i_c/X1
tests/offset/shape_type_i_c/X2
tests/offset/shape_type_i_c/X3
tests/offset/shape_type_i_c/X4
tests/offset/shape_type_i_c/X5
tests/offset/shape_type_i_c/X6
tests/offset/shape_type_i_c/XA1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XA2 [new file with mode: 0644]
tests/offset/shape_type_i_c/XA3 [new file with mode: 0644]
tests/offset/shape_type_i_c/XA4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XA5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XA6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XA7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XA8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XA9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XB1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XB2 [new file with mode: 0644]
tests/offset/shape_type_i_c/XB3 [new file with mode: 0644]
tests/offset/shape_type_i_c/XB4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XB5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XB6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XB7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XB8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XB9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XC1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XC2 [new file with mode: 0755]
tests/offset/shape_type_i_c/XC3 [new file with mode: 0644]
tests/offset/shape_type_i_c/XC4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XC5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XC6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XC7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XC8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XC9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XD1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XD2 [new file with mode: 0644]
tests/offset/shape_type_i_c/XD3 [new file with mode: 0755]
tests/offset/shape_type_i_c/XD4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XD5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XD6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XD7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XD8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XD9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XE1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XE2 [new file with mode: 0644]
tests/offset/shape_type_i_c/XE3 [new file with mode: 0644]
tests/offset/shape_type_i_c/XE4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XE5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XE6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XE7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XE8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XE9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XF1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XF2 [new file with mode: 0644]
tests/offset/shape_type_i_c/XF3 [new file with mode: 0644]
tests/offset/shape_type_i_c/XF4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XF5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XF6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XF7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XF8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XF9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XG1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XG2 [new file with mode: 0644]
tests/offset/shape_type_i_c/XG3 [new file with mode: 0644]
tests/offset/shape_type_i_c/XG4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XG5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XG6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XG7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XG8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XG9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XH1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XH2 [new file with mode: 0644]
tests/offset/shape_type_i_c/XH3 [new file with mode: 0644]
tests/offset/shape_type_i_c/XH4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XH5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XH6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XH7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XH8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XH9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XI1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XI2 [new file with mode: 0644]
tests/offset/shape_type_i_c/XI3 [new file with mode: 0644]
tests/offset/shape_type_i_c/XI4 [new file with mode: 0755]
tests/offset/shape_type_i_c/XI5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XI6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XI7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XI8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XI9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XJ1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XJ2 [new file with mode: 0755]
tests/offset/shape_type_i_c/XJ3 [new file with mode: 0644]
tests/offset/shape_type_i_c/XJ4 [new file with mode: 0644]
tests/offset/shape_type_i_c/XJ5 [new file with mode: 0644]
tests/offset/shape_type_i_c/XJ6 [new file with mode: 0644]
tests/offset/shape_type_i_c/XJ7 [new file with mode: 0644]
tests/offset/shape_type_i_c/XJ8 [new file with mode: 0644]
tests/offset/shape_type_i_c/XJ9 [new file with mode: 0644]
tests/offset/shape_type_i_c/XK1 [new file with mode: 0644]
tests/offset/shape_type_i_c/XK2 [new file with mode: 0644]
tests/offset/shape_type_i_c/Y1 [new file with mode: 0644]
tests/offset/shape_type_i_c/Y2 [new file with mode: 0644]
tests/offset/shape_type_i_c/Y3 [new file with mode: 0644]
tests/offset/shape_type_i_c/Y4 [new file with mode: 0644]
tests/offset/shape_type_i_c/Y5 [new file with mode: 0644]
tests/offset/shape_type_i_c/Y6 [new file with mode: 0644]
tests/offset/shape_type_i_c/Y7 [new file with mode: 0644]
tests/offset/shape_type_i_c/Y8 [new file with mode: 0644]
tests/offset/shape_type_i_c/Y9 [new file with mode: 0644]
tests/offset/shape_type_i_c/Z1 [new file with mode: 0644]
tests/offset/shape_type_i_c/Z2 [new file with mode: 0644]
tests/offset/shape_type_i_c/Z3 [new file with mode: 0644]
tests/offset/shape_type_i_c/Z4 [new file with mode: 0644]
tests/offset/shape_type_i_c/Z5 [new file with mode: 0644]
tests/offset/shape_type_i_c/Z6 [new file with mode: 0644]
tests/offset/shape_type_i_c/Z7 [new file with mode: 0644]
tests/offset/shape_type_i_c/Z8 [new file with mode: 0644]
tests/offset/shape_type_i_c/Z9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZA1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZA2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZA3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZA4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZA5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZA6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZA7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZA8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZA9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZB1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZB2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZB3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZB4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZB5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZB6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZB7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZB8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZB9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZC9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZD1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZD2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZD3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZD4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZD5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZD6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZD7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZD8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZD9 [new file with mode: 0755]
tests/offset/shape_type_i_c/ZE1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZE2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZE3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZE4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZE5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZE6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZE7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZE8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZE9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZF1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZF2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZF3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZF4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZF5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZF6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZF7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZF8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZF9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZG1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZG2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZG3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZG4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZG5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZG6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZG7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZG8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZG9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZH1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZH2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZH3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZH4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZH5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZH6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZH7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZH8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZH9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZI1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZI2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZI3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZI4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZI5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZI6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZI7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZI8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZI9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZJ1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZJ2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZJ3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZJ4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZJ5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZJ6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZJ7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZJ8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZJ9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZK1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZK2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZK3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZK4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZK5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZK6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZK7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZK8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZK9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZL1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZL2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZL3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZL4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZL5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZL6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZL7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZL8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZL9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZM1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZM2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZM3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZM4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZM5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZM6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZM7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZM8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZM9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZN1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZN2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZN3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZN4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZN5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZN6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZN7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZN8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZN9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZO1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZO2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZO3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZO4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZO5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZO6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZO7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZO8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZO9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZP1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZP2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZP3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZP4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZP5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZP6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZP7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZP8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZP9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZQ1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZQ2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZQ3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZQ4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZQ5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZQ6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZQ7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZQ8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZQ9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZR1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZR2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZR3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZR4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZR5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZR6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZR7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZR8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZR9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZS1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZS2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZS3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZS4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZS5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZS6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZS7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZS8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZS9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZT1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZT2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZT3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZT4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZT5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZT6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZT7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZT8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZT9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZU1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZU2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZU3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZU4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZU5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZU6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZU7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZU8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZU9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZV1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZV2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZV3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZV4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZV5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZV6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZV7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZV8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZV9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZW1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZW2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZW3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZW4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZW5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZW6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZW7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZW8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZW9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZX1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZX2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZX3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZX4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZX5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZX6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZX7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZX8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZX9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZY1 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZY2 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZY3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZY4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZY5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZY6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZY7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZY8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZY9 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZZ1 [new file with mode: 0755]
tests/offset/shape_type_i_c/ZZ2 [new file with mode: 0755]
tests/offset/shape_type_i_c/ZZ3 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZZ4 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZZ5 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZZ6 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZZ7 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZZ8 [new file with mode: 0644]
tests/offset/shape_type_i_c/ZZ9 [new file with mode: 0644]

index 7d07bbc..bf88a8b 100644 (file)
@@ -176,7 +176,11 @@ void BOPAlgo_Builder::PrepareHistory()
   aItM.Initialize(aMS);
   for (; aItM.More(); aItM.Next()) {
     const TopoDS_Shape& aSx=aItM.Key();
-    aType=aSx.ShapeType();
+    aType = aSx.ShapeType();
+    if (!(aType == TopAbs_VERTEX || aType == TopAbs_EDGE || 
+          aType == TopAbs_FACE   || aType == TopAbs_SOLID)) {
+      continue;
+    }
     //
     // 4.1 .myImagesResult
     bHasImage=myImages.IsBound(aSx); 
index 591dd30..38b7be5 100644 (file)
@@ -228,7 +228,6 @@ void BOPAlgo_PaveFiller::PerformFF()
       //
       bToIntersect = CheckPlanes(nF1, nF2);
       if (!bToIntersect) {
-        myDS->AddInterf(nF1, nF2);
         BOPDS_InterfFF& aFF=aFFs.Append1();
         aFF.SetIndices(nF1, nF2);
         aFF.Init(0, 0);
index 8dd8716..6aee96c 100644 (file)
@@ -150,8 +150,12 @@ void BOPTools_AlgoTools::MakeSplitEdge(const TopoDS_Edge&   aE,
   E.EmptyCopy();
   //
   BRep_Builder BB;
-  BB.Add  (E, aV1);
-  BB.Add  (E, aV2);
+  if (!aV1.IsNull()) {
+    BB.Add  (E, aV1);
+  }
+  if (!aV2.IsNull()) {
+    BB.Add  (E, aV2);
+  }
   BB.Range(E, aP1, aP2);
   BB.UpdateEdge(E, aTol);
   aNewEdge=E;
index 016e09f..778e7d9 100644 (file)
@@ -115,84 +115,115 @@ static TopoDS_Vertex CommonVertex(TopoDS_Edge& E1,
 
 //=======================================================================
 //function : Store
-//purpose  : The vertices are added despite of the coincidence with
+//purpose  : Store the vertices <theLV> into AsDes for the edge <theEdge>.
+//           The vertices are added despite of the coincidence with
 //           already added vertices. When all vertices for all edges
 //           are added the coinciding chains of vertices should be fused
 //           using FuseVertices() method.
 //=======================================================================
-static void  Store (const TopoDS_Edge&     E1,
-                    const TopoDS_Edge&     E2,
-                    const TopTools_ListOfShape&  LV1,
-                    const TopTools_ListOfShape&  LV2,
-                    Handle(BRepAlgo_AsDes) AsDes,
-                    Standard_Real          Tol,
-                    TopTools_IndexedDataMapOfShapeListOfShape& aDMVV)
+static void Store(const TopoDS_Edge& theEdge,
+                  const TopTools_ListOfShape& theLV,
+                  const Standard_Real theTol,
+                  const Standard_Boolean IsToUpdate,
+                  Handle(BRepAlgo_AsDes) theAsDes2d,
+                  TopTools_IndexedDataMapOfShapeListOfShape& theDMVV)
 {
-  BRep_Builder aBB;
-  for (Standard_Integer i = 0; i < 2; ++i) {
-    const TopoDS_Edge& aE = !i ? E1 : E2;
-    const TopTools_ListOfShape& aLV = !i ? LV1 : LV2;
-    const TopTools_ListOfShape& aLVEx = AsDes->Descendant(aE);
-    if (aLVEx.IsEmpty()) {
-      if (aLV.Extent()) AsDes->Add(aE, aLV);
+  const TopTools_ListOfShape& aLVEx = theAsDes2d->Descendant(theEdge);
+  if (!IsToUpdate && aLVEx.IsEmpty()) {
+    if (theLV.Extent()) theAsDes2d->Add(theEdge, theLV);
+    return;
+  }
+  //
+  GeomAPI_ProjectPointOnCurve aProjPC;
+  if (IsToUpdate) {
+    Standard_Real aT1, aT2;
+    const Handle(Geom_Curve)& aC = BRep_Tool::Curve(theEdge, aT1, aT2);
+    aProjPC.Init(aC, aT1, aT2);
+  }
+  //
+  TopTools_MapOfShape aMV;
+  TopTools_ListIteratorOfListOfShape aIt(theLV);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Vertex& aV = TopoDS::Vertex(aIt.Value());
+    if (!aMV.Add(aV)) {
       continue;
     }
     //
-    TopTools_MapOfShape aMV;
-    TopTools_ListIteratorOfListOfShape aIt(aLV);
-    for (; aIt.More(); aIt.Next()) {
-      const TopoDS_Vertex& aV = TopoDS::Vertex(aIt.Value());
-      if (!aMV.Add(aV)) {
-        continue;
+    const gp_Pnt& aP = BRep_Tool::Pnt(aV);
+    //
+    TopTools_ListOfShape aLVC;
+    TopTools_ListIteratorOfListOfShape aItEx(aLVEx);
+    for (; aItEx.More(); aItEx.Next()) {
+      const TopoDS_Vertex& aVEx = TopoDS::Vertex(aItEx.Value());
+      if (aV.IsSame(aVEx)) {
+        break;
       }
-      gp_Pnt aP = BRep_Tool::Pnt(aV);
-      //
-      TopTools_ListOfShape aLVC;
-      TopTools_ListIteratorOfListOfShape aItEx(aLVEx);
-      for (; aItEx.More(); aItEx.Next()) {
-        const TopoDS_Vertex& aVEx = TopoDS::Vertex(aItEx.Value());
-        if (aV.IsSame(aVEx)) {
-          break;
-        }
-        gp_Pnt aPEx = BRep_Tool::Pnt(aVEx);
-        //
-        if (aP.IsEqual(aPEx, Tol)) {
-          aLVC.Append(aVEx);
-        }
+      const gp_Pnt& aPEx = BRep_Tool::Pnt(aVEx);
+      if (aP.IsEqual(aPEx, theTol)) {
+        aLVC.Append(aVEx);
+      }
+    }
+    //
+    if (aItEx.More()) {
+      continue;
+    }
+    //
+    if (IsToUpdate) {
+      // get parameter of the vertex on the edge
+      aProjPC.Perform(aP);
+      if (!aProjPC.NbPoints()) {
+        continue;
       }
       //
-      if (aItEx.More()) {
+      if (aProjPC.LowerDistance() > theTol) {
         continue;
       }
       //
-      if (aLVC.Extent()) {
-        TopTools_ListOfShape aLVN;
-        aLVN.Append(aV);
-        //
-        TopTools_ListIteratorOfListOfShape aItLV(aLVC);
-        for (; aItLV.More(); aItLV.Next()) {
-          const TopoDS_Shape& aVC = aItLV.Value();
-          TopTools_ListOfShape* pLV = aDMVV.ChangeSeek(aVC);
-          if (!pLV) {
-            aDMVV.Add(aVC, aLVN);
-          }
-          else {
-            pLV->Append(aV);
-          }
-        }
-        //
-        TopTools_ListOfShape* pLV = aDMVV.ChangeSeek(aV);
+      Standard_Real aT = aProjPC.LowerDistanceParameter();
+      TopoDS_Shape aLocalShape = aV.Oriented(TopAbs_INTERNAL);
+      BRep_Builder().UpdateVertex(TopoDS::Vertex(aLocalShape), aT, theEdge, theTol);
+    }
+    else {
+      BRep_Builder().UpdateVertex(aV, theTol);
+    }
+    //
+    if (aLVC.Extent()) {
+      TopTools_ListIteratorOfListOfShape aItLV(aLVC);
+      for (; aItLV.More(); aItLV.Next()) {
+        const TopoDS_Shape& aVC = aItLV.Value();
+        TopTools_ListOfShape* pLV = theDMVV.ChangeSeek(aVC);
         if (!pLV) {
-          aDMVV.Add(aV, aLVC);
-        }
-        else {
-          pLV->Append(aLVC);
+          pLV = &theDMVV(theDMVV.Add(aVC, TopTools_ListOfShape()));
         }
+        pLV->Append(aV);
       }
       //
-      aBB.UpdateVertex(aV, Tol);
-      AsDes->Add(aE, aV);
+      TopTools_ListOfShape* pLV = theDMVV.ChangeSeek(aV);
+      if (!pLV) {
+        pLV = &theDMVV(theDMVV.Add(aV, TopTools_ListOfShape()));
+      }
+      pLV->Append(aLVC);
     }
+    theAsDes2d->Add(theEdge, aV);
+  }
+}
+
+//=======================================================================
+//function : Store
+//purpose  : Store the intersection vertices between two edges into AsDes
+//=======================================================================
+static void  Store (const TopoDS_Edge& theE1,
+                    const TopoDS_Edge& theE2,
+                    const TopTools_ListOfShape& theLV1,
+                    const TopTools_ListOfShape& theLV2,
+                    const Standard_Real theTol,
+                    Handle(BRepAlgo_AsDes) theAsDes2d,
+                    TopTools_IndexedDataMapOfShapeListOfShape& theDMVV)
+{
+  for (Standard_Integer i = 0; i < 2; ++i) {
+    const TopoDS_Edge& aE = !i ? theE1 : theE2;
+    const TopTools_ListOfShape& aLV = !i ? theLV1 : theLV2;
+    Store(aE, aLV, theTol, Standard_False, theAsDes2d, theDMVV);
   }
 }
 
@@ -453,7 +484,7 @@ static void EdgeInter(const TopoDS_Face&              F,
     //---------------------------------
     Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
     TolStore = Max(TolStore, 10.*Tol);
-    Store (E1,E2,LV1,LV2,AsDes,TolStore, aDMVV);
+    Store (E1,E2,LV1,LV2,TolStore,AsDes, aDMVV);
   }
 }
 //=======================================================================
@@ -469,7 +500,8 @@ static void RefEdgeInter(const TopoDS_Face&              F,
                          Standard_Real                   Tol,
                          Standard_Boolean                WithOri,
                          gp_Pnt&                         Pref,
-                         TopTools_IndexedDataMapOfShapeListOfShape& aDMVV)
+                         TopTools_IndexedDataMapOfShapeListOfShape& aDMVV,
+                         Standard_Boolean&               theCoincide)
 {
 #ifdef DRAW
   if (Inter2dAffichInt2d) {
@@ -480,7 +512,9 @@ static void RefEdgeInter(const TopoDS_Face&              F,
     DBRep::Set(name,E2);
   }
 #endif
-
+  //
+  theCoincide = Standard_False;
+  //
   if (E1.IsSame(E2))
     return;
 
@@ -531,6 +565,14 @@ static void RefEdgeInter(const TopoDS_Face&              F,
   Geom2dAdaptor_Curve GAC1(pcurve1, f[1], l[1]);
   Geom2dAdaptor_Curve GAC2(pcurve2, f[2], l[2]);
   Geom2dInt_GInter Inter2d( GAC1, GAC2, TolDub, TolDub );
+  //
+  if (!Inter2d.IsDone() || !Inter2d.NbPoints()) {
+    theCoincide = (Inter2d.NbSegments() &&
+                  (GAC1.GetType() == GeomAbs_Line) &&
+                  (GAC2.GetType() == GeomAbs_Line));
+    return;
+  }
+  //
   for (i = 1; i <= Inter2d.NbPoints(); i++)
     {
       gp_Pnt P3d;
@@ -723,7 +765,7 @@ static void RefEdgeInter(const TopoDS_Face&              F,
 ////-----------------------------------------------------
     Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
     TolStore = Max(TolStore, 10.*Tol);
-    Store (E1,E2,LV1,LV2,AsDes,TolStore, aDMVV);
+    Store (E1,E2,LV1,LV2,TolStore,AsDes, aDMVV);
   }
 }
 
@@ -848,7 +890,7 @@ static Standard_Boolean ExtendPCurve(const Handle(Geom2d_Curve)& aPCurve,
 
 //  Modified by skv - Fri Dec 26 17:00:55 2003 OCC4455 Begin
 //static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE) 
-static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE, const Standard_Real theOffset)
+void BRepOffset_Inter2d::ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE, const Standard_Real theOffset)
 {
   //BRepLib::BuildCurve3d(E);
 
@@ -1380,20 +1422,16 @@ void BRepOffset_Inter2d::Compute (const Handle(BRepAlgo_AsDes)&     AsDes,
 //function : ConnexIntByInt
 //purpose  : 
 //=======================================================================
-
-//  Modified by skv - Fri Dec 26 16:53:16 2003 OCC4455 Begin
-//  Add another parameter: offset value.
 void BRepOffset_Inter2d::ConnexIntByInt
-(const TopoDS_Face&            FI,
- BRepOffset_Offset&            OFI,
- TopTools_DataMapOfShapeShape& MES,
- const TopTools_DataMapOfShapeShape& Build,
- const Handle(BRepAlgo_AsDes)& AsDes,
- const Handle(BRepAlgo_AsDes)& AsDes2d,
- const Standard_Real           Offset,
- const Standard_Real           Tol,
- TopTools_IndexedDataMapOfShapeListOfShape& theDMVV)
-//  Modified by skv - Fri Dec 26 16:53:18 2003 OCC4455 End
+ (const TopoDS_Face&            FI,
+  BRepOffset_Offset&            OFI,
+  TopTools_DataMapOfShapeShape& MES,
+  const TopTools_DataMapOfShapeShape& Build,
+  const Handle(BRepAlgo_AsDes)& AsDes2d,
+  const Standard_Real           Offset,
+  const Standard_Real           Tol,
+  TopTools_IndexedMapOfShape&   FacesWithVerts,
+  TopTools_IndexedDataMapOfShapeListOfShape& theDMVV)
 {  
 
   TopTools_DataMapOfShapeListOfShape MVE;
@@ -1417,12 +1455,8 @@ void BRepOffset_Inter2d::ConnexIntByInt
         const TopoDS_Edge& EI = TopoDS::Edge(itL.Value());
         TopoDS_Shape aLocalShape = OFI.Generated(EI);
         const TopoDS_Edge& OE = TopoDS::Edge(aLocalShape);
-//        const TopoDS_Edge& OE = TopoDS::Edge(OFI.Generated(EI));
         if (!MES.IsBound(OE) && !Build.IsBound(EI)) {
-//  Modified by skv - Fri Dec 26 16:59:52 2003 OCC4455 Begin
-//          ExtentEdge(OE,NE);
           ExtentEdge(OE,NE, Offset);
-//  Modified by skv - Fri Dec 26 16:59:54 2003 OCC4455 End
           MES.Bind  (OE,NE);
         }
       }
@@ -1432,14 +1466,6 @@ void BRepOffset_Inter2d::ConnexIntByInt
   TopoDS_Face           FIO = TopoDS::Face(OFI.Face());
   if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO));
   //
-  TopTools_MapOfShape aME;
-  const TopTools_ListOfShape& aLE = AsDes->Descendant(FIO);
-  TopTools_ListIteratorOfListOfShape aItLE(aLE);
-  for (; aItLE.More(); aItLE.Next()) {
-    const TopoDS_Shape& aE = aItLE.Value();
-    aME.Add(aE);
-  }
-  //
   BRepAdaptor_Surface BAsurf(FIO);
   
   TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
@@ -1454,8 +1480,6 @@ void BRepOffset_Inter2d::ConnexIntByInt
     wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace));
     if (!wexp.More())
       continue; // Protection from case when explorer does not contain edges.
-//    wexp.Init(TopoDS::Wire(W .Oriented(TopAbs_FORWARD)),
-//              TopoDS::Face(FI.Oriented(TopAbs_FORWARD)));
     CurE = FirstE  = wexp.Current(); 
     while (!end) {
       wexp.Next();
@@ -1467,17 +1491,13 @@ void BRepOffset_Inter2d::ConnexIntByInt
       }
       if (CurE.IsSame(NextE)) continue;
 
-      //IFV------------
       TopoDS_Vertex Vref = CommonVertex(CurE, NextE); 
       gp_Pnt Pref = BRep_Tool::Pnt(Vref);
-      //IFV------------
 
       TopoDS_Shape aLocalShape = OFI.Generated(CurE);
       TopoDS_Edge CEO = TopoDS::Edge(aLocalShape);
       aLocalShape = OFI.Generated(NextE);
       TopoDS_Edge NEO = TopoDS::Edge(aLocalShape);
-//      TopoDS_Edge CEO = TopoDS::Edge(OFI.Generated(CurE));
-//      TopoDS_Edge NEO = TopoDS::Edge(OFI.Generated(NextE));
       //------------------------------------------
       // Inter processing of images of CurE NextE.
       //------------------------------------------
@@ -1490,7 +1510,7 @@ void BRepOffset_Inter2d::ConnexIntByInt
         NE2 = Build(NextE);
       }
       else if (Build.IsBound(CurE) && MES.IsBound(NEO)) {
-         NE1 = Build(CurE);
+        NE1 = Build(CurE);
         NE2 = MES  (NEO);
       }
       else if (Build.IsBound(NextE) && MES.IsBound(CEO)) {
@@ -1504,43 +1524,31 @@ void BRepOffset_Inter2d::ConnexIntByInt
         //------------------------------------
         // NE1,NE2 can be a compound of Edges.
         //------------------------------------
-        TopExp_Explorer Exp1,Exp2;
-        for (Exp1.Init(NE1,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) {
-          for (Exp2.Init(NE2,TopAbs_EDGE) ; Exp2.More(); Exp2.Next()) {
-            RefEdgeInter(FIO,BAsurf,TopoDS::Edge(Exp1.Current()),TopoDS::Edge(Exp2.Current()),
-                      AsDes2d,Tol,Standard_True/*Standard_False*/, Pref, theDMVV);
+        Standard_Boolean bCoincide;
+        TopExp_Explorer Exp1, Exp2;
+        for (Exp1.Init(NE1, TopAbs_EDGE); Exp1.More(); Exp1.Next()) {
+          const TopoDS_Edge& aE1 = TopoDS::Edge(Exp1.Current());
+          for (Exp2.Init(NE2, TopAbs_EDGE); Exp2.More(); Exp2.Next()) {
+            const TopoDS_Edge& aE2 = TopoDS::Edge(Exp2.Current());
+            RefEdgeInter(FIO, BAsurf, aE1, aE2, AsDes2d,
+                         Tol, Standard_True, Pref, theDMVV, bCoincide);
           }
         }
         //
+        // check if some of the offset edges have been
+        // generated out of the common vertex
         if (Build.IsBound(Vref)) {
-          TopoDS_Shape NE3 = Build(Vref);
-          //
-          for (Exp2.Init(NE3,TopAbs_EDGE) ; Exp2.More(); Exp2.Next()) {
-            const TopoDS_Edge& aE3 = *(TopoDS_Edge*)&Exp2.Current();
-            if (!aME.Contains(aE3)) {
-              continue;
-            }
-            //
-            for (Exp1.Init(NE1,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) {
-              RefEdgeInter(FIO,BAsurf,TopoDS::Edge(Exp1.Current()),aE3,
-                           AsDes2d,Tol,Standard_True/*Standard_False*/, Pref, theDMVV);
-            }
-            //
-            for (Exp1.Init(NE2,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) {
-              RefEdgeInter(FIO,BAsurf,TopoDS::Edge(Exp1.Current()),aE3,
-                           AsDes2d,Tol,Standard_True/*Standard_False*/, Pref, theDMVV);
-            }
-          }
+          FacesWithVerts.Add(FI);
         }
       }
       else {
         if (MES.IsBound(CEO)) {
-          TopoDS_Vertex  V = CommonVertex(CEO,NEO); 
+          TopoDS_Vertex  V = CommonVertex(CEO,NEO);
           UpdateVertex  (V,CEO,TopoDS::Edge(MES(CEO)),Tol);
           AsDes2d->Add     (MES(CEO),V);
         }
         else if (MES.IsBound(NEO)) {
-          TopoDS_Vertex V = CommonVertex(CEO,NEO); 
+          TopoDS_Vertex V = CommonVertex(CEO,NEO);
           UpdateVertex (V,NEO,TopoDS::Edge(MES(NEO)),Tol);
           AsDes2d->Add    (MES(NEO),V);
         }
@@ -1551,6 +1559,143 @@ void BRepOffset_Inter2d::ConnexIntByInt
 }
 
 //=======================================================================
+//function : ConnexIntByIntInVert
+//purpose  : Intersection of the edges generated out of vertices
+//=======================================================================
+void BRepOffset_Inter2d::ConnexIntByIntInVert
+ (const TopoDS_Face&            FI,
+  BRepOffset_Offset&            OFI,
+  TopTools_DataMapOfShapeShape& MES,
+  const TopTools_DataMapOfShapeShape& Build,
+  const Handle(BRepAlgo_AsDes)& AsDes,
+  const Handle(BRepAlgo_AsDes)& AsDes2d,
+  const Standard_Real           Tol,
+  TopTools_IndexedDataMapOfShapeListOfShape& theDMVV)
+{
+  TopoDS_Face           FIO = TopoDS::Face(OFI.Face());
+  if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO));
+  //
+  TopTools_MapOfShape aME;
+  const TopTools_ListOfShape& aLE = AsDes->Descendant(FIO);
+  TopTools_ListIteratorOfListOfShape aItLE(aLE);
+  for (; aItLE.More(); aItLE.Next()) {
+    const TopoDS_Shape& aE = aItLE.Value();
+    aME.Add(aE);
+  }
+  //
+  BRepAdaptor_Surface BAsurf(FIO);
+  //
+  TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
+  for (; exp.More(); exp.Next()) {
+    const TopoDS_Wire&     W = TopoDS::Wire(exp.Current());
+    //
+    BRepTools_WireExplorer wexp;
+    Standard_Boolean       end = Standard_False ;
+    TopoDS_Edge            FirstE,CurE,NextE;
+    //
+    TopoDS_Shape aLocalWire = W .Oriented(TopAbs_FORWARD);
+    TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD);
+    wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace));
+    if (!wexp.More())
+      continue; // Protection from case when explorer does not contain edges.
+    //
+    CurE = FirstE  = wexp.Current(); 
+    while (!end) {
+      wexp.Next();
+      if (wexp.More()) {
+        NextE = wexp.Current();
+      } 
+      else {
+        NextE = FirstE; end = Standard_True;
+      }
+      if (CurE.IsSame(NextE)) continue;
+      //
+      TopoDS_Vertex Vref = CommonVertex(CurE, NextE); 
+      gp_Pnt Pref = BRep_Tool::Pnt(Vref);
+      if (!Build.IsBound(Vref)) {
+        CurE = NextE;
+        continue;
+      }
+      //
+      TopoDS_Shape aLocalShape = OFI.Generated(CurE);
+      TopoDS_Edge CEO = TopoDS::Edge(aLocalShape);
+      aLocalShape = OFI.Generated(NextE);
+      TopoDS_Edge NEO = TopoDS::Edge(aLocalShape);
+      //
+      TopoDS_Shape         NE1,NE2;
+      
+      if (Build.IsBound(CurE) && Build.IsBound(NextE)) {
+        NE1 = Build(CurE );
+        NE2 = Build(NextE);
+      }
+      else if (Build.IsBound(CurE) && MES.IsBound(NEO)) {
+        NE1 = Build(CurE);
+        NE2 = MES  (NEO);
+      }
+      else if (Build.IsBound(NextE) && MES.IsBound(CEO)) {
+        NE1 = Build(NextE);
+        NE2 = MES(CEO);
+      }
+      else {
+        CurE = NextE;
+        continue;
+      }
+      //
+      TopExp_Explorer Exp1, Exp2;
+      Standard_Boolean bCoincide;
+      // intersect edges generated from vertex with the edges of the face
+      TopoDS_Shape NE3 = Build(Vref);
+      //
+      for (Exp2.Init(NE3, TopAbs_EDGE); Exp2.More(); Exp2.Next()) {
+        const TopoDS_Edge& aE3 = *(TopoDS_Edge*)&Exp2.Current();
+        if (!aME.Contains(aE3)) {
+          continue;
+        }
+        //
+        // intersection with first edge
+        for (Exp1.Init(NE1, TopAbs_EDGE); Exp1.More(); Exp1.Next()) {
+          const TopoDS_Edge& aE1 = TopoDS::Edge(Exp1.Current());
+          RefEdgeInter(FIO, BAsurf, aE1, aE3, AsDes2d,
+            Tol, Standard_True, Pref, theDMVV, bCoincide);
+          if (bCoincide) {
+            // in case of coincidence trim the edge E3 the same way as E1
+            Store(aE3, AsDes2d->Descendant(aE1), Tol, Standard_True, AsDes2d, theDMVV);
+          }
+        }
+        //
+        // intersection with second edge
+        for (Exp1.Init(NE2, TopAbs_EDGE); Exp1.More(); Exp1.Next()) {
+          const TopoDS_Edge& aE2 = TopoDS::Edge(Exp1.Current());
+          RefEdgeInter(FIO, BAsurf, aE2, aE3, AsDes2d,
+            Tol, Standard_True, Pref, theDMVV, bCoincide);
+          if (bCoincide) {
+            // in case of coincidence trim the edge E3 the same way as E2
+            Store(aE3, AsDes2d->Descendant(aE2), Tol, Standard_True, AsDes2d, theDMVV);
+          }
+        }
+        //
+        // intersection of the edges generated from vertex
+        // among themselves
+        for (Exp1.Init(NE3, TopAbs_EDGE); Exp1.More(); Exp1.Next()) {
+          if (aE3.IsSame(Exp1.Current())) {
+            break;
+          }
+        }
+        //
+        for (Exp1.Next(); Exp1.More(); Exp1.Next()) {
+          const TopoDS_Edge& aE3Next = TopoDS::Edge(Exp1.Current());
+          if (aME.Contains(aE3Next)) {
+            RefEdgeInter(FIO, BAsurf, aE3Next, aE3, AsDes2d,
+              Tol, Standard_True, Pref, theDMVV, bCoincide);
+          }
+        }
+      }
+      CurE = NextE;
+    }
+  }
+}
+
+//=======================================================================
 //function : MakeChain
 //purpose  : 
 //=======================================================================
index 5254350..4c06890 100644 (file)
@@ -51,27 +51,45 @@ public:
                                        const Standard_Real Tol,
                                        TopTools_IndexedDataMapOfShapeListOfShape& theDMVV);
 
-  //! Computes the intersection between the offset edges
-  //! stored in AsDes as descendatnds on <F>. All intersection
-  //! vertices will be stored in AsDes2d. When all faces of the
-  //! shape are treated the intersection vertices have to be fused
-  //! using the FuseVertices method.
+  //! Computes the intersection between the offset edges of the <FI>.
+  //! All intersection vertices will be stored in AsDes2d.
+  //! When all faces of the shape are treated the intersection vertices
+  //! have to be fused using the FuseVertices method.
   //! theDMVV contains the vertices that should be fused.
-  Standard_EXPORT static void ConnexIntByInt (const TopoDS_Face& FI, 
-                                              BRepOffset_Offset& OFI, 
-                                              TopTools_DataMapOfShapeShape& MES, 
-                                              const TopTools_DataMapOfShapeShape& Build, 
-                                              const Handle(BRepAlgo_AsDes)& AsDes, 
-                                              const Handle(BRepAlgo_AsDes)& AsDes2d, 
-                                              const Standard_Real Offset, 
+  Standard_EXPORT static void ConnexIntByInt (const TopoDS_Face& FI,
+                                              BRepOffset_Offset& OFI,
+                                              TopTools_DataMapOfShapeShape& MES,
+                                              const TopTools_DataMapOfShapeShape& Build,
+                                              const Handle(BRepAlgo_AsDes)& AsDes2d,
+                                              const Standard_Real Offset,
                                               const Standard_Real Tol,
+                                              TopTools_IndexedMapOfShape& FacesWithVerts,
                                               TopTools_IndexedDataMapOfShapeListOfShape& theDMVV);
 
+  //! Computes the intersection between the offset edges generated
+  //! from vertices and stored into AsDes as descendants of the <FI>.
+  //! All intersection vertices will be stored in AsDes2d.
+  //! When all faces of the shape are treated the intersection vertices
+  //! have to be fused using the FuseVertices method.
+  //! theDMVV contains the vertices that should be fused.
+  Standard_EXPORT static void ConnexIntByIntInVert (const TopoDS_Face& FI,
+                                                    BRepOffset_Offset& OFI,
+                                                    TopTools_DataMapOfShapeShape& MES,
+                                                    const TopTools_DataMapOfShapeShape& Build,
+                                                    const Handle(BRepAlgo_AsDes)& AsDes,
+                                                    const Handle(BRepAlgo_AsDes)& AsDes2d,
+                                                    const Standard_Real Tol,
+                                                    TopTools_IndexedDataMapOfShapeListOfShape& theDMVV);
+
   //! Fuses the chains of vertices in the theDMVV
   //! and updates AsDes by replacing the old vertices
   //! with the new ones.
   Standard_EXPORT static void FuseVertices(const TopTools_IndexedDataMapOfShapeListOfShape& theDMVV,
                                            const Handle(BRepAlgo_AsDes)& theAsDes);
+  //! extents the edge
+  Standard_EXPORT static void ExtentEdge(const TopoDS_Edge& E,
+                                         TopoDS_Edge& NE,
+                                         const Standard_Real theOffset);
 
 protected:
 
index 0297153..56b539c 100644 (file)
@@ -45,6 +45,8 @@
 #include <TopTools_ListIteratorOfListOfShape.hxx>
 #include <TopTools_MapIteratorOfMapOfShape.hxx>
 #include <TopTools_MapOfShape.hxx>
+//
+#include <BOPTools_AlgoTools.hxx>
 
 //=======================================================================
 //function : BRepOffset_Inter3d
@@ -444,51 +446,24 @@ void BRepOffset_Inter3d::ConnexIntByInt
     TopExp::MapShapesAndAncestors(SI, TopAbs_VERTEX, TopAbs_FACE, aMVF);
   }
   //
-  aNb = VEmap.Extent();
-  for (i = 1; i <= aNb; ++i) {
-    const TopoDS_Shape& aS = VEmap(i);
-    //
-    TopoDS_Edge E;
-    TopTools_ListOfShape aLF1, aLF2;
-    //
-    bEdge = (aS.ShapeType() == TopAbs_EDGE);
-    if (bEdge) {
-      // faces connected by the edge
-      E = *(TopoDS_Edge*)&aS;
-      //
-      const BRepOffset_ListOfInterval& L = Analyse.Type(E);
-      if (L.IsEmpty()) {
-        continue;
-      }
-      //
-      BRepOffset_Type    OT   = L.First().Type();
-      if (OT != BRepOffset_Convex && OT != BRepOffset_Concave) {
-        continue;
-      }
-      //
-      if (OT == BRepOffset_Concave) CurSide = TopAbs_IN;
-      else                          CurSide = TopAbs_OUT;
-      //-----------------------------------------------------------
-      // edge is of the proper type, return adjacent faces.
-      //-----------------------------------------------------------
-      const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
-      if (Anc.Extent() != 2) {
+  TopTools_DataMapOfShapeListOfShape aDMVLF1, aDMVLF2;
+  TopTools_IndexedDataMapOfShapeListOfShape aDMIntE, aDMIntFF;
+  //
+  if (bIsPlanar) {
+    aNb = VEmap.Extent();
+    for (i = 1; i <= aNb; ++i) {
+      const TopoDS_Shape& aS = VEmap(i);
+      if (aS.ShapeType() != TopAbs_VERTEX) {
         continue;
       }
       //
-      F1  = TopoDS::Face(Anc.First());
-      F2  = TopoDS::Face(Anc.Last ());
-      //
-      aLF1.Append(F1);
-      aLF2.Append(F2);
-    }
-    else {
       // faces connected by the vertex
       const TopTools_ListOfShape& aLF = aMVF.FindFromKey(aS);
       if (aLF.Extent() < 2) {
         continue;
       }
       //
+      TopTools_ListOfShape aLF1, aLF2;
       Standard_Boolean bVertexOnly = Standard_False;
       TopTools_MapOfShape aMFence;
       //
@@ -534,6 +509,57 @@ void BRepOffset_Inter3d::ConnexIntByInt
         continue;
       }
       //
+      aDMVLF1.Bind(aS, aLF1);
+      aDMVLF2.Bind(aS, aLF2);
+    }
+  }
+  //
+  aNb = VEmap.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aS = VEmap(i);
+    //
+    TopoDS_Edge E;
+    TopTools_ListOfShape aLF1, aLF2;
+    //
+    bEdge = (aS.ShapeType() == TopAbs_EDGE);
+    if (bEdge) {
+      // faces connected by the edge
+      E = *(TopoDS_Edge*)&aS;
+      //
+      const BRepOffset_ListOfInterval& L = Analyse.Type(E);
+      if (L.IsEmpty()) {
+        continue;
+      }
+      //
+      BRepOffset_Type    OT   = L.First().Type();
+      if (OT != BRepOffset_Convex && OT != BRepOffset_Concave) {
+        continue;
+      }
+      //
+      if (OT == BRepOffset_Concave) CurSide = TopAbs_IN;
+      else                          CurSide = TopAbs_OUT;
+      //-----------------------------------------------------------
+      // edge is of the proper type, return adjacent faces.
+      //-----------------------------------------------------------
+      const TopTools_ListOfShape& Anc = Analyse.Ancestors(E);
+      if (Anc.Extent() != 2) {
+        continue;
+      }
+      //
+      F1  = TopoDS::Face(Anc.First());
+      F2  = TopoDS::Face(Anc.Last ());
+      //
+      aLF1.Append(F1);
+      aLF2.Append(F2);
+    }
+    else {
+      if (!aDMVLF1.IsBound(aS)) {
+        continue;
+      }
+      //
+      aLF1 = aDMVLF1.Find(aS);
+      aLF2 = aDMVLF2.Find(aS);
+      //
       CurSide = mySide;
     }
     //
@@ -595,6 +621,24 @@ void BRepOffset_Inter3d::ConnexIntByInt
           for (; it.More(); it.Next()) {
             const TopoDS_Shape& aNE = it.Value();
             B.Add(C, aNE);
+            if (bEdge) {
+              TopoDS_Vertex aVO1, aVO2;
+              TopExp::Vertices(TopoDS::Edge(aS), aVO1, aVO2);
+              if (!aDMVLF1.IsBound(aVO1) && !aDMVLF1.IsBound(aVO2)) {
+                TopTools_ListOfShape *pListS = aDMIntE.ChangeSeek(aNE);
+                if (!pListS) {
+                  pListS = &aDMIntE.ChangeFromIndex(aDMIntE.Add(aNE, TopTools_ListOfShape()));
+                }
+                pListS->Append(aS);
+                //
+                if (!aDMIntFF.Contains(aNE)) {
+                  TopTools_ListOfShape aLFF;
+                  aLFF.Append(NF1);
+                  aLFF.Append(NF2);
+                  aDMIntFF.Add(aNE, aLFF);
+                }
+              }
+            }
           }
           //
           Build.Bind(aS,C);
@@ -620,14 +664,33 @@ void BRepOffset_Inter3d::ConnexIntByInt
             }
           }
           //
+          TopTools_ListOfShape aLENew;
           for (it.Initialize(aLInt1) ; it.More(); it.Next()) {
             const TopoDS_Shape &anE1 = it.Value();
             //
             for (it1.Initialize(aLInt2) ; it1.More(); it1.Next()) {
               const TopoDS_Shape &anE2 = it1.Value();
-              
-              if (anE1.IsSame(anE2))
+              if (anE1.IsSame(anE2)) {
                 B.Add(C, anE1);
+                if (bEdge) {
+                  TopoDS_Vertex aVO1, aVO2;
+                  TopExp::Vertices(TopoDS::Edge(aS), aVO1, aVO2);
+                  if (!aDMVLF1.IsBound(aVO1) && !aDMVLF1.IsBound(aVO2)) {
+                    TopTools_ListOfShape *pListS = aDMIntE.ChangeSeek(anE1);
+                    if (!pListS) {
+                      pListS = &aDMIntE.ChangeFromIndex(aDMIntE.Add(anE1, TopTools_ListOfShape()));
+                    }
+                    pListS->Append(aS);
+                    //
+                    if (!aDMIntFF.Contains(anE1)) {
+                      TopTools_ListOfShape aLFF;
+                      aLFF.Append(NF1);
+                      aLFF.Append(NF2);
+                      aDMIntFF.Add(anE1, aLFF);
+                    }
+                  }
+                }
+              }
             }
           }
           Build.Bind(aS,C);
@@ -639,6 +702,70 @@ void BRepOffset_Inter3d::ConnexIntByInt
     }
     //  Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 End
   }
+  //
+  aNb = aDMIntE.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopTools_ListOfShape& aLE = aDMIntE(i);
+    if (aLE.Extent() == 1) {
+      continue;
+    }
+    //
+    // make connexity blocks of edges
+    TopoDS_Compound aCE;
+    B.MakeCompound(aCE);
+    //
+    TopTools_ListIteratorOfListOfShape aItLE(aLE);
+    for (; aItLE.More(); aItLE.Next()) {
+      const TopoDS_Shape& aE = aItLE.Value();
+      B.Add(aCE, aE);
+    }
+    //
+    TopTools_ListOfShape aLCBE;
+    BOPTools_AlgoTools::MakeConnexityBlocks(aCE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
+    if (aLCBE.Extent() == 1) {
+      continue;
+    }
+    //
+    const TopoDS_Edge& aE = TopoDS::Edge(aDMIntE.FindKey(i));
+    const TopTools_ListOfShape& aLFF = aDMIntFF.FindFromKey(aE);
+    const TopoDS_Shape& aF1 = aLFF.First();
+    const TopoDS_Shape& aF2 = aLFF.Last();
+    //
+    aItLE.Initialize(aLCBE);
+    for (aItLE.Next(); aItLE.More(); aItLE.Next()) {
+      // make new edge with different tedge instance
+      TopoDS_Edge aNewEdge;
+      TopoDS_Vertex aV1, aV2;
+      Standard_Real aT1, aT2;
+      //
+      TopExp::Vertices(aE, aV1, aV2);
+      BRep_Tool::Range(aE, aT1, aT2);
+      //
+      BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aNewEdge);
+      //
+      myAsDes->Add(aF1, aNewEdge);
+      myAsDes->Add(aF2, aNewEdge);
+      //
+      const TopoDS_Shape& aCB = aItLE.Value();
+      TopoDS_Iterator aItCB(aCB);
+      for (; aItCB.More(); aItCB.Next()) {
+        const TopoDS_Shape& aS = aItCB.Value();
+        TopoDS_Shape& aCI = Build.ChangeFind(aS);
+        //
+        TopoDS_Compound aNewCI;
+        B.MakeCompound(aNewCI);
+        TopExp_Explorer aExp(aCI, TopAbs_EDGE);
+        for (; aExp.More(); aExp.Next()) {
+          const TopoDS_Shape& aSx = aExp.Current();
+          if (!aSx.IsSame(aE)) {
+            B.Add(aNewCI, aSx);
+          }
+        }
+        B.Add(aNewCI, aNewEdge);
+        aCI = aNewCI;
+      }
+    }
+  }
 }
 
 //=======================================================================
index 8fa0fd1..9fea562 100644 (file)
 #include <Geom_Line.hxx>
 #include <NCollection_Vector.hxx>
 //
-#include <BOPAlgo_PaveFiller.hxx>
-#include <BOPAlgo_Builder.hxx>
 #include <BOPAlgo_MakerVolume.hxx>
-#include <BOPCol_ListOfShape.hxx>
-#include <BOPCol_DataMapOfShapeShape.hxx>
-#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
-#include <BOPTools.hxx>
-#include <BOPTools_AlgoTools3D.hxx>
 #include <BOPTools_AlgoTools.hxx>
-#include <IntTools_Context.hxx>
-#include <IntTools_ShrunkRange.hxx>
-#include <CPnts_AbscissaPoint.hxx>
+#include <BOPCol_ListOfShape.hxx>
 
 #include <stdio.h>
 // POP for NT
@@ -253,43 +244,24 @@ static void DEBVerticesControl (const TopTools_IndexedMapOfShape& NewEdges,
 //=======================================================================
 // static methods
 //=======================================================================
-static 
-  void SortFaces(const TopTools_ListOfShape& theLIm, 
-                 TopTools_ListOfShape& theLFImages,
-                 const Standard_Boolean bKeepFirst);
-
-static 
-  Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
-                             const TopoDS_Shape& theSWhere,
-                             TopoDS_Shape& theRes);
-
-static 
-  void UpdateOrigins(TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-                     BOPAlgo_Builder& theGF);
-
-static 
-  Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
-                                    const Handle(IntTools_Context)& theCtx);
+static
+  void GetEnlargedFaces(const TopoDS_Shape& theShape,
+                        const BRepOffset_DataMapOfShapeOffset& theMapSF,
+                        const TopTools_DataMapOfShapeShape& theMES,
+                        TopTools_DataMapOfShapeShape& theFacesOrigins,
+                        BRepAlgo_Image& theImage,
+                        TopTools_ListOfShape& theLSF);
 
-static 
-  Standard_Boolean ComputeBiNormal(const TopoDS_Face& theF,
-                                   const TopoDS_Edge& theE,
-                                   gp_Dir& theDB);
-static 
-  Standard_Boolean CheckBiNormals(const TopoDS_Face& aFIm,
-                                  const TopoDS_Face& aFOr,
-                                  const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-                                  const TopTools_MapOfShape& theMFence,
-                                  Standard_Boolean& bKeep,
-                                  Standard_Boolean& bRem,
-                                  const Standard_Boolean RemoveInvalidFaces);
+static
+  Standard_Boolean BuildShellsCompleteInter(const BOPCol_ListOfShape& theLF,
+                                            const BOPCol_IndexedDataMapOfShapeListOfShape& theOrigins,
+                                            BRepAlgo_Image& theImage,
+                                            TopoDS_Shape& theShells);
 
-static 
-  void CheckBiNormals(TopTools_ListOfShape&  theLFImages,
-                      const TopoDS_Face& theF,
-                      const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-                      TopTools_ListOfShape& theLFKeep,
-                      const Standard_Boolean RemoveInvalidFaces);
+static
+  Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
+                                const TopAbs_ShapeEnum theSSType,
+                                TopoDS_Shape& theResult);
 
 static 
   Standard_Boolean CheckNormals(const TopoDS_Face& theFIm,
@@ -316,6 +288,28 @@ static
 static
   Standard_Boolean IsPlanar(const TopoDS_Shape& theS);
 
+static
+  void TrimEdge(TopoDS_Edge&                  NE,
+                const Handle(BRepAlgo_AsDes)& AsDes2d,
+                Handle(BRepAlgo_AsDes)& AsDes,
+                TopTools_DataMapOfShapeShape& theETrimEInf);
+
+static 
+  void TrimEdges(const TopoDS_Shape& theShape,
+                 const Standard_Real theOffset,
+                 BRepOffset_DataMapOfShapeOffset& theMapSF,
+                 TopTools_DataMapOfShapeShape& theMES,
+                 TopTools_DataMapOfShapeShape& theBuild,
+                 Handle(BRepAlgo_AsDes)& theAsDes,
+                 Handle(BRepAlgo_AsDes)& theAsDes2d,
+                 TopTools_IndexedMapOfShape& theNewEdges,
+                 TopTools_DataMapOfShapeShape& theETrimEInf,
+                 TopTools_DataMapOfShapeListOfShape& theEdgesOrigins);
+
+static
+  void AppendToList(TopTools_ListOfShape& theL,
+                    const TopoDS_Shape& theS);
+
 static BRepOffset_Error checkSinglePoint(const Standard_Real theUParam,
                                          const Standard_Real theVParam,
                                          const Handle(Geom_Surface)& theSurf,
@@ -544,7 +538,6 @@ static void FillContours(const TopoDS_Shape& aShape,
     }
 }
 
-
 //
 //-----------------------------------------------------------------------
 //
@@ -572,8 +565,7 @@ BRepOffset_MakeOffset::BRepOffset_MakeOffset(const TopoDS_Shape&    S,
                                              const Standard_Boolean SelfInter, 
                                              const GeomAbs_JoinType Join,
                                              const Standard_Boolean Thickening,
-                                             const Standard_Boolean RemoveIntEdges,
-                                             const Standard_Boolean RemInvFaces)
+                                             const Standard_Boolean RemoveIntEdges)
 : 
 myOffset     (Offset),
 myTol        (Tol),
@@ -584,9 +576,7 @@ mySelfInter  (SelfInter),
 myJoin       (Join),
 myThickening    (Thickening),
 myRemoveIntEdges(RemoveIntEdges),
-myRemoveInvalidFaces(RemInvFaces),
 myDone     (Standard_False)
-
 {
   myAsDes = new BRepAlgo_AsDes();
   MakeOffsetShape();
@@ -606,8 +596,7 @@ void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S,
                                        const Standard_Boolean SelfInter,
                                        const GeomAbs_JoinType Join,
                                        const Standard_Boolean Thickening,
-                                       const Standard_Boolean RemoveIntEdges,
-                                       const Standard_Boolean RemInvFaces)
+                                       const Standard_Boolean RemoveIntEdges)
 {
   myOffset     = Offset;
   myShape      = S;
@@ -618,7 +607,6 @@ void BRepOffset_MakeOffset::Initialize(const TopoDS_Shape&    S,
   myJoin       = Join;
   myThickening     = Thickening;
   myRemoveIntEdges = RemoveIntEdges;
-  myRemoveInvalidFaces = RemInvFaces;
   myDone     = Standard_False;
   myIsPerformSewing = Standard_False;
   myIsPlanar = Standard_False;
@@ -847,6 +835,11 @@ void BRepOffset_MakeOffset::MakeOffsetShape()
   // Construction of shells.
   //-------------------------
   MakeShells ();
+  if (myOffsetShape.IsNull()) {
+    // not done
+    myDone = Standard_False;
+    return;
+  }
   //--------------
   // Unwinding 3D.
   //--------------
@@ -1021,125 +1014,33 @@ const TopoDS_Shape&  BRepOffset_MakeOffset::Shape() const
 }
 
 //=======================================================================
-//function : TrimEdge
-//purpose  : Trim the edge of the largest of descendants in AsDes2d.
-//           Order in AsDes two vertices that have trimmed the edge.
+//function : MakeOffsetFaces
+//purpose  : 
 //=======================================================================
-void TrimEdge(TopoDS_Edge&                  NE,
-              const Handle(BRepAlgo_AsDes)& AsDes2d,
-              Handle(BRepAlgo_AsDes)& AsDes)
+void BRepOffset_MakeOffset::MakeOffsetFaces(BRepOffset_DataMapOfShapeOffset& theMapSF)
 {
-  Standard_Real aSameParTol = Precision::Confusion();
-  
-  TopoDS_Vertex V1,V2;
-  Standard_Real U = 0.;
-  Standard_Real UMin =  Precision::Infinite();
-  Standard_Real UMax = -UMin;
-
-  const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
+  Standard_Real aCurOffset;
+  TopTools_ListOfShape aLF;
+  TopTools_DataMapOfShapeShape ShapeTgt;
+  TopTools_ListIteratorOfListOfShape aItLF;
   //
-  Standard_Boolean bTrim = Standard_False;
+  Standard_Boolean OffsetOutside = (myOffset > 0.);
   //
-  if (LE.Extent() > 1) {
-    TopTools_ListIteratorOfListOfShape it (LE);
-    for (; it.More(); it.Next()) {
-      TopoDS_Vertex V = TopoDS::Vertex(it.Value());
-      if (NE.Orientation() == TopAbs_REVERSED)
-        V.Reverse();
-      //V.Orientation(TopAbs_INTERNAL);
-      if (!FindParameter(V, NE, U)) {
-        Standard_Real f, l;
-        Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
-        gp_Pnt thePoint = BRep_Tool::Pnt(V);
-        GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
-        if (Projector.NbPoints() == 0)
-          Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge no projection");
-        U = Projector.LowerDistanceParameter();
-      }
-      if (U < UMin) {
-        UMin = U; V1   = V;
-      }
-      if (U > UMax) {
-        UMax = U; V2   = V;
-      }
-    }
-    //
-    if (V1.IsNull() || V2.IsNull()) {
-      Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge");
-    }
-    if (!V1.IsSame(V2)) {
-      NE.Free( Standard_True );
-      BRep_Builder B;
-      TopAbs_Orientation Or = NE.Orientation();
-      NE.Orientation(TopAbs_FORWARD);
-      TopoDS_Vertex VF,VL;
-      TopExp::Vertices (NE,VF,VL);
-      B.Remove(NE,VF);
-      B.Remove(NE,VL);
-      B.Add  (NE,V1.Oriented(TopAbs_FORWARD));
-      B.Add  (NE,V2.Oriented(TopAbs_REVERSED));
-      B.Range(NE,UMin,UMax);
-      NE.Orientation(Or);
-      AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
-      AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
-      BRepLib::SameParameter(NE, aSameParTol, Standard_True);
-      //
-      bTrim = Standard_True;
-    }
-  }
+  BRepLib::SortFaces(myShape, aLF);
   //
-  if (!bTrim) {
-    BRepAdaptor_Curve aBAC(NE);
-    if (aBAC.GetType() == GeomAbs_Line) {
-      if (AsDes->HasAscendant(NE)) {
-        AsDes->Remove(NE);
-      }
-    }
-  }
-}
-
-//=======================================================================
-//function : BuildOffsetByInter
-//purpose  : 
-//=======================================================================
-void BRepOffset_MakeOffset::BuildOffsetByInter()
-{
-#ifdef OCCT_DEBUG
-  if ( ChronBuild) {
-    cout << " CONSTRUCTION OF OFFSETS :" << endl;
-    Clock.Reset();
-    Clock.Start();
-  }
-#endif
-
-  BRepOffset_DataMapOfShapeOffset MapSF;
-  TopTools_MapOfShape             Done;
-  Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
-  //--------------------------------------------------------
-  // Construction of faces parallel to initial faces
-  //--------------------------------------------------------
-  TopExp_Explorer Exp;
-  TopTools_ListOfShape LF;
-  TopTools_ListIteratorOfListOfShape itLF;
-
-  BRepLib::SortFaces(myShape,LF);
-
-  TopTools_DataMapOfShapeShape ShapeTgt;
-  for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
-    const TopoDS_Face&   F = TopoDS::Face(itLF.Value());
-    Standard_Real CurOffset = myOffset;
-    if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
-    BRepOffset_Offset    OF(F,CurOffset,ShapeTgt,OffsetOutside,myJoin);
+  aItLF.Initialize(aLF);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Face& aF = TopoDS::Face(aItLF.Value());
+    aCurOffset = myFaceOffset.IsBound(aF) ? myFaceOffset(aF) : myOffset;
+    BRepOffset_Offset OF(aF, aCurOffset, ShapeTgt, OffsetOutside, myJoin);
     TopTools_ListOfShape Let;
-    myAnalyse.Edges(F,BRepOffset_Tangent,Let);
-    TopTools_ListIteratorOfListOfShape itl(Let);
-    
-    for ( ; itl.More(); itl.Next()) {
+    myAnalyse.Edges(aF,BRepOffset_Tangent,Let);
+    TopTools_ListIteratorOfListOfShape itl(Let);    
+    for (; itl.More(); itl.Next()) {
       const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
       if ( !ShapeTgt.IsBound(Cur)) {
         TopoDS_Shape aLocalShape = OF.Generated(Cur);
         const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
-//        const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
         ShapeTgt.Bind(Cur,OF.Generated(Cur));
         TopoDS_Vertex V1,V2,OV1,OV2;
         TopExp::Vertices (Cur,V1,V2);
@@ -1160,8 +1061,32 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
         }
       }
     }
-    MapSF.Bind(F,OF);
+    theMapSF.Bind(aF,OF);
+  }
+}
+
+//=======================================================================
+//function : BuildOffsetByInter
+//purpose  : 
+//=======================================================================
+void BRepOffset_MakeOffset::BuildOffsetByInter()
+{
+#ifdef OCCT_DEBUG
+  if ( ChronBuild) {
+    cout << " CONSTRUCTION OF OFFSETS :" << endl;
+    Clock.Reset();
+    Clock.Start();
   }
+#endif
+
+  TopExp_Explorer Exp, Exp2, ExpC;
+  TopTools_ListIteratorOfListOfShape itLF;
+  
+  //--------------------------------------------------------
+  // Construction of faces parallel to initial faces
+  //--------------------------------------------------------
+  BRepOffset_DataMapOfShapeOffset MapSF;
+  MakeOffsetFaces(MapSF);
   //--------------------------------------------------------------------
   // MES   : Map of OffsetShape -> Extended Shapes.
   // Build : Map of Initial SS  -> OffsetShape build by Inter.
@@ -1189,148 +1114,29 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
   //---------------------------------------------------------------------------------
   // Extension of neighbor edges of new edges and intersection between neighbors.
   //--------------------------------------------------------------------------------
-  TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
   Handle(BRepAlgo_AsDes) AsDes2d = new BRepAlgo_AsDes();
-  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next())
-  {
-    const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
-    Standard_Real aCurrFaceTol = BRep_Tool::Tolerance(FI);
-    BRepOffset_Inter2d::ConnexIntByInt (FI, MapSF(FI), MES, Build, 
-                                        AsDes, AsDes2d, myOffset, aCurrFaceTol, aDMVV);
-  }
-  //
-  // fuse vertices on edges
-  BRepOffset_Inter2d::FuseVertices(aDMVV, AsDes2d);
+  IntersectEdges(myShape, MapSF, MES, Build, AsDes, AsDes2d);
   //-----------------------------------------------------------
   // Great restriction of new edges and update of AsDes.
   //------------------------------------------ ----------------
+  TopTools_DataMapOfShapeListOfShape anEdgesOrigins; // offset edge - initial edges
   TopTools_IndexedMapOfShape NewEdges;
-  TopExp_Explorer Exp2,ExpC;
-  TopoDS_Shape    NE;
-  TopoDS_Edge     TNE;
-  TopoDS_Face     NF;
-  TopTools_IndexedDataMapOfShapeListOfShape anOrigins;
-  
-  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
-    const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
-    NF = MapSF(FI).Face();
-    if (MES.IsBound(NF)) {
-      NF = TopoDS::Face(MES(NF));
-    }
-    //
-    TopTools_MapOfShape View;
-    TopTools_IndexedMapOfShape VEmap;
-    Standard_Integer i, aNb;
-    //
-    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
-    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
-    //
-    aNb = VEmap.Extent();
-    for (i = 1; i <= aNb; ++i) {
-      const TopoDS_Shape& aS = VEmap(i);
-      if (!View.Add(aS)) {
-        continue;
-      }
-      //
-      if (Build.IsBound(aS)) {
-        NE = Build(aS);
-        if (NE.ShapeType() == TopAbs_EDGE) {
-          if (anOrigins.Contains(NE)) {
-            anOrigins.ChangeFromKey(NE).Append(aS);
-          }
-          else {
-            TopTools_ListOfShape aLSx;
-            aLSx.Append(aS);
-            anOrigins.Add(NE, aLSx);
-          }
-          //
-          if (NewEdges.Add(NE)) {
-            TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);
-          }
-        }
-        else {
-          //------------------------------------------------------------
-          // The Intersections are on several edges.
-          // The pieces without intersections with neighbors  
-          // are removed from AsDes.
-          //------------------------------------------------------------
-          for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
-            TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
-            if (NewEdges.Add(NEC)) {
-              NEC.Free(Standard_True);
-              if (anOrigins.Contains(NEC)) {
-                anOrigins.ChangeFromKey(NEC).Append(aS);
-              }
-              else {
-                TopTools_ListOfShape aLSx;
-                aLSx.Append(aS);
-                anOrigins.Add(NEC, aLSx);
-              }
-              //
-              if (!AsDes2d->Descendant(NEC).IsEmpty()) {
-                TrimEdge (NEC,AsDes2d,AsDes);
-              }
-              else {
-                if (AsDes->HasAscendant(NEC)) {
-                  AsDes->Remove(NEC);
-                }
-              }
-            }
-          }
-        }
-      }
-      else {
-        if (aS.ShapeType() != TopAbs_EDGE) {
-          continue;
-        }
-        //
-        NE = MapSF(FI).Generated(aS);
-        //// modified by jgv, 19.12.03 for OCC4455 ////
-        NE.Orientation(aS.Orientation());
-        if (anOrigins.Contains(NE)) {
-          anOrigins.ChangeFromKey(NE).Append(aS);
-        }
-        else {
-          TopTools_ListOfShape aLSx;
-          aLSx.Append(aS);
-          anOrigins.Add(NE, aLSx);
-        }
-        //
-        if (MES.IsBound(NE)) {
-          NE = MES(NE);
-          NE.Orientation(aS.Orientation());
-          if (NewEdges.Add(NE)) {TrimEdge (TopoDS::Edge(NE),AsDes2d,AsDes);} 
-        }
-        AsDes->Add(NF,NE);
-      } 
-    }
-  }
-  
+  TopTools_DataMapOfShapeShape aETrimEInf; // trimmed - not trimmed edges
+  //
+  //Map of edges obtained after FACE-FACE (offsetted) intersection.
+  //Key1 is edge trimmed by intersection points with other edges;
+  //Item is not-trimmed edge. 
+  TrimEdges(myShape, myOffset, MapSF, MES, Build, AsDes, AsDes2d, NewEdges, aETrimEInf, anEdgesOrigins);
+  //
   //--------------------------------- 
   // Intersection 2D on //
   //---------------------------------  
+  TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
+  TopTools_DataMapOfShapeShape aFacesOrigins; // offset face - initial face
   TopTools_ListOfShape LFE; 
   BRepAlgo_Image     IMOE;
-  for (Exp.Init(myShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
-    const TopoDS_Shape& FI  = Exp.Current();
-    const TopoDS_Shape& OFI = MapSF(FI).Face();
-    if (MES.IsBound(OFI)) {
-      const TopoDS_Face& aLocalFace = TopoDS::Face(MES(OFI));
-      LFE.Append(aLocalFace);
-      IMOE.SetRoot(aLocalFace);
-      //
-      if (anOrigins.Contains(aLocalFace)) {
-        anOrigins.ChangeFromKey(aLocalFace).Append(FI);
-      }
-      else {
-        TopTools_ListOfShape aLSx;
-        aLSx.Append(FI);
-        anOrigins.Add(aLocalFace, aLSx);
-      }
-    }
-  }
-  
-  aDMVV.Clear();
+  GetEnlargedFaces(myShape, MapSF, MES, aFacesOrigins, IMOE, LFE);
+  //
   TopTools_ListIteratorOfListOfShape itLFE(LFE);
   for (; itLFE.More(); itLFE.Next())
   {
@@ -1356,28 +1162,13 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
   //
   TopTools_MapOfShape aMFDone;
   //
-  if ((myJoin == GeomAbs_Intersection) && myInter) {
-    TopTools_ListOfShape aLFailed;
-    BuildSplitsOfFaces(LFE, AsDes, anOrigins, IMOE, aLFailed, Standard_False);
-    if (aLFailed.Extent()) {
-      myMakeLoops.Build(aLFailed, AsDes, IMOE);
-    }
+  if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
+    BuildSplitsOfExtendedFaces(LFE, AsDes, anEdgesOrigins, aFacesOrigins, aETrimEInf, IMOE);
     //
-    if (LFE.Extent() != aLFailed.Extent()) {
-      TopTools_MapOfShape aMFailed;
-      TopTools_ListIteratorOfListOfShape aItLF(aLFailed);
-      for (; aItLF.More(); aItLF.Next()) {
-        const TopoDS_Shape& aS = aItLF.Value();
-        aMFailed.Add(aS);
-      }
-      //
-      aItLF.Initialize(LFE);
-      for (; aItLF.More(); aItLF.Next()) {
-        const TopoDS_Shape& aS = aItLF.Value();
-        if (!aMFailed.Contains(aS)) {
-          aMFDone.Add(aS);
-        }
-      }
+    TopTools_ListIteratorOfListOfShape aItLF(LFE);
+    for (; aItLF.More(); aItLF.Next()) {
+      const TopoDS_Shape& aS = aItLF.Value();
+      aMFDone.Add(aS);
     }
   }
   else {
@@ -1578,7 +1369,7 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
 //  Modified by skv - Tue Mar 15 16:20:43 2005
 
   //---------------------------
-  // MAJ SD. for caps 
+  // MAJ SD. for caps
   //---------------------------
   //TopTools_MapOfShape View; 
   for (i = 1; i <= myFaces.Extent(); i++) {
@@ -1631,390 +1422,28 @@ void BRepOffset_MakeOffset::BuildOffsetByInter()
 }
 
 //=======================================================================
-//function : BuildSplitsOfFaces
+//function : BuildOffsetByArc
 //purpose  : 
 //=======================================================================
-void BRepOffset_MakeOffset::BuildSplitsOfFaces
-  (const TopTools_ListOfShape& theLF,
-   const Handle(BRepAlgo_AsDes)& theAsDes,
-   TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-   BRepAlgo_Image& theImage,
-   TopTools_ListOfShape& theLFailed,
-   const Standard_Boolean bLimited)
+void BRepOffset_MakeOffset::BuildOffsetByArc()
 {
-  if (!myIsPlanar) {
-    theLFailed.Assign(theLF);
-    return;
-  }
-  //
-  BOPCol_ListOfShape aLS, aLF;
-  BOPCol_ListIteratorOfListOfShape aIt;
-  TopTools_ListIteratorOfListOfShape aItLF, aItLE, aItLE1;
-  TopTools_DataMapOfShapeListOfShape anEImages;
-  BRep_Builder aBB;
-  TopoDS_Compound aFaces;
-  //
-  aBB.MakeCompound(aFaces);
-  //
-  // firstly it is necessary to fuse all the edges
-  Handle(IntTools_Context) aCtx = new IntTools_Context();
-  //
-  aItLF.Initialize(theLF);
-  for (; aItLF.More(); aItLF.Next()) {
-    const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
-    //
-    const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
-    aItLE.Initialize(aLE);
-    for (; aItLE.More(); aItLE.Next()) {
-      const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
-      if (BRep_Tool::Degenerated(aE)) {
-        continue;
-      }
-      //
-      if (ProcessMicroEdge(aE, aCtx)) {
-        continue;
-      }
-      //
-      aLS.Append(aE);
-    }
-  }
-  //
-  if (aLS.Extent() > 1) {
-    BOPAlgo_Builder aGFE;
-    //
-    aGFE.SetArguments(aLS);
-    aGFE.Perform();
-    if (aGFE.ErrorStatus() == 0) {
-      // fill map with edges images
-      aIt.Initialize(aLS);
-      for (; aIt.More(); aIt.Next()) {
-        const TopoDS_Shape& aE = aIt.Value();
-        //
-        const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE);
-        if (aLEIm.Extent()) {
-          anEImages.Bind(aE, aLEIm);
-        }
-      }
-      //
-      UpdateOrigins(theOrigins, aGFE);
-    }
-  }
-  //
-  // now we can split the faces
-  aItLF.Initialize(theLF);
-  for (; aItLF.More(); aItLF.Next()) {
-    const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
-    //
-    // the offset face
-    aLS.Clear();
-    aLS.Append(aF.Oriented(TopAbs_FORWARD));
-    //
-    Standard_Integer iCountE = 0;
-    TopTools_MapOfShape aMFE;
-    TopExp_Explorer aExp(aF, TopAbs_EDGE);
-    for (; aExp.More(); aExp.Next()) {
-      const TopoDS_Shape& aE = aExp.Current();
-      if (anEImages.IsBound(aE)) {
-        const TopTools_ListOfShape& aLEIm = anEImages.Find(aE);
-        aItLE.Initialize(aLEIm);
-        for (; aItLE.More(); aItLE.Next()) {
-          const TopoDS_Shape& aEIm = aItLE.Value();
-          aMFE.Add(aEIm);
-        }
-      }
-      else {
-        aMFE.Add(aE);
-      }
-    }
-    //
-    // the edges by which the offset face should be split
-    const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
-    aItLE.Initialize(aLE);
-    for (; aItLE.More(); aItLE.Next()) {
-      const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
-      if (BRep_Tool::Degenerated(aE)) {
-        continue;
-      }
-      //
-      if (anEImages.IsBound(aE)) {
-        const TopTools_ListOfShape& aLEIm = anEImages.Find(aE);
-        aItLE1.Initialize(aLEIm);
-        for (; aItLE1.More(); aItLE1.Next()) {
-          const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aItLE1.Value();
-          // check for micro edge
-          if (ProcessMicroEdge(aEIm, aCtx)) {
-            continue;
-          }
-          //
-          aLS.Append(aEIm);
-          if (!aMFE.Contains(aEIm)) {
-            ++iCountE;
-          }
-        }
-      }
-      else {
-        if (ProcessMicroEdge(aE, aCtx)) {
-          continue;
-        }
-        aLS.Append(aE);
-        if (!aMFE.Contains(aE)) {
-          ++iCountE;
-        }
-      }
-    }
-    //
-    TopTools_ListOfShape aLFImages;
-    //
-    // split the face by the edges
-    if (!iCountE) {
-      if (bLimited && !theImage.HasImage(aF)) {
-        aLFImages.Append(aF);
-        theImage.Bind(aF, aLFImages);
-        aBB.Add(aFaces, aF);
-      }
-      continue;
-    }
-    //
-    BOPAlgo_Builder aGF;
-    //
-    aGF.SetArguments(aLS);
-    aGF.Perform();
-    if (aGF.ErrorStatus()) {
-      theLFailed.Append(aF);
-      continue;
-    }
-    //
-    // splits of the offset shape
-    aLFImages = aGF.Modified(aF);
-    if (aLFImages.IsEmpty()) {
-      theLFailed.Append(aF);
-      continue;
-    }
-    //
-    TopTools_MapOfShape aME;
-    // collect images of Edges
-    aItLE.Initialize(aLE);
-    for (; aItLE.More(); aItLE.Next()) {
-      const TopoDS_Shape& aE = aItLE.Value();
-      if (anEImages.IsBound(aE)) {
-        TopTools_MapOfShape aMFence;
-        TopTools_ListOfShape aLEImNew;
-        Standard_Boolean bModif = Standard_False;
-        //
-        TopTools_ListOfShape& aLEIm = anEImages.ChangeFind(aE);
-        aItLE1.Initialize(aLEIm);
-        for (; aItLE1.More(); aItLE1.Next()) {
-          const TopoDS_Shape& aEIm = aItLE1.Value();
-          const TopTools_ListOfShape& aLEImIm = aGF.Modified(aEIm);
-          if (aLEImIm.Extent()) {
-            bModif = Standard_True;
-            TopTools_ListIteratorOfListOfShape aItLEIm(aLEImIm);
-            for (; aItLEIm.More(); aItLEIm.Next()) {
-              const TopoDS_Shape& aEImIm = aItLEIm.Value();
-              if (aMFence.Add(aEImIm)) {
-                aLEImNew.Append(aEImIm);
-                aME.Add(aEImIm);
-              }
-            }
-          }
-          else {
-            aLEImNew.Append(aEIm);
-            aME.Add(aEIm);
-          }
-        }
-        //
-        if (bModif) {
-          aLEIm.Assign(aLEImNew);
-        }
-      }
-      else {
-        const TopTools_ListOfShape& aLEIm = aGF.Modified(aE);
-        if (aLEIm.Extent()) {
-          anEImages.Bind(aE, aLEIm);
-          TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
-          for (; aItLEIm.More(); aItLEIm.Next()) {
-            const TopoDS_Shape& aEIm = aItLEIm.Value();
-            aME.Add(aEIm);
-          }
-        }
-        else {
-          aME.Add(aE);
-        }
-      }
-    }
-    //
-    if (!bLimited) {
-      //
-      // to overcome the often errors in trimming edges it is 
-      // better to remove first the faces containing the boundaries
-      // of the extended surfaces;
-      Standard_Boolean bKeep;
-      aItLE.Initialize(aLFImages);
-      for (; aItLE.More();) {
-        const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLE.Value();
-        //
-        aExp.Init(aFIm, TopAbs_EDGE);
-        for (bKeep = Standard_True; aExp.More() && bKeep; aExp.Next()) {
-          const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
-          //
-          if (BRep_Tool::Degenerated(aE)) {
-            continue;
-          }
-          //
-          bKeep = aME.Contains(aE);
-        }
-        //
-        if (bKeep) {
-          aItLE.Next();
-        }
-        else {
-          aLFImages.Remove(aItLE);
-        }
-      }
-      //
-      UpdateOrigins(theOrigins, aGF);
-      //
-      if (aLFImages.Extent() >= 1) {
-        TopTools_ListOfShape aLFKeep;
-        //
-        // check offset faces on the coincidence of the 
-        // bi-normal directions with the original faces
-        CheckBiNormals(aLFImages, aF, theOrigins, aLFKeep, myRemoveInvalidFaces);
-        //
-        // limit the face
-        if (aLFImages.Extent() > 1) {
-          TopTools_ListOfShape aLFTmp = aLFImages;
-          aLFImages.Clear();
-          //
-          SortFaces(aLFTmp, aLFImages, Standard_True);
-        }
-        //
-        if (aLFKeep.Extent()) {
-          TopTools_MapOfShape aMFence;
-          aItLE.Initialize(aLFImages);
-          for (; aItLE.More(); aItLE.Next()) {
-            const TopoDS_Shape& aFIm = aItLE.Value();
-            aMFence.Add(aFIm);
-          }
-          //
-          aItLE.Initialize(aLFKeep);
-          for (; aItLE.More(); aItLE.Next()) {
-            const TopoDS_Shape& aFIm = aItLE.Value();
-            if (aMFence.Add(aFIm)) {
-              aLFImages.Append(aFIm);
-            }
-          }
-        }
-      }
-    }
-    //
-    // Fill history for faces
-    if (aLFImages.Extent()) {
-      if (theImage.HasImage(aF)) {
-        theImage.Add(aF, aLFImages);
-      }
-      else {
-        theImage.Bind(aF, aLFImages);
-      }
-    }
-    //
-    aItLE.Initialize(aLFImages);
-    for (; aItLE.More(); aItLE.Next()) {
-      const TopoDS_Shape& aFIm = aItLE.Value();
-      aBB.Add(aFaces, aFIm);
-    }
-  }
-  //
-  // fill history for edges
-  TopTools_IndexedMapOfShape aMFE;
-  TopExp::MapShapes(aFaces, TopAbs_EDGE, aMFE);
-  //
-  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItEIm(anEImages);
-  for (; aItEIm.More(); aItEIm.Next()) {
-    const TopoDS_Shape& aE = aItEIm.Key();
-    const TopTools_ListOfShape& aLEIm = aItEIm.Value();
-    //
-    Standard_Boolean bHasImage = theImage.HasImage(aE);
-    aItLE.Initialize(aLEIm);
-    for (; aItLE.More(); aItLE.Next()) {
-      const TopoDS_Shape& aEIm = aItLE.Value();
-      if (aMFE.Contains(aEIm)) {
-        if (bHasImage) {
-          theImage.Add(aE, aEIm);
-        }
-        else {
-          theImage.Bind(aE, aEIm);
-          bHasImage = Standard_True;
-        }
-      }
-    }
-  }
-}
-
-//=======================================================================
-//function : BuildOffsetByArc
-//purpose  : 
-//=======================================================================
-void BRepOffset_MakeOffset::BuildOffsetByArc()
-{
-#ifdef OCCT_DEBUG
-  if ( ChronBuild) {
-    cout << " CONSTRUCTION OF OFFSETS :" << endl;
-    Clock.Reset();
-    Clock.Start();
+#ifdef OCCT_DEBUG
+  if ( ChronBuild) {
+    cout << " CONSTRUCTION OF OFFSETS :" << endl;
+    Clock.Reset();
+    Clock.Start();
   }
 #endif
 
-  BRepOffset_DataMapOfShapeOffset MapSF;
-  TopTools_MapOfShape             Done;
-  Standard_Boolean OffsetOutside = (myOffset > 0.)? Standard_True : Standard_False;
+  TopExp_Explorer Exp;
+  TopTools_ListIteratorOfListOfShape itLF;
+  TopTools_MapOfShape Done;
+  
   //--------------------------------------------------------
   // Construction of faces parallel to initial faces
   //--------------------------------------------------------
-  TopExp_Explorer Exp;
-  TopTools_ListOfShape LF;
-  TopTools_ListIteratorOfListOfShape itLF;
-
-  BRepLib::SortFaces(myShape,LF);
-
-  TopTools_DataMapOfShapeShape EdgeTgt;
-  for (itLF.Initialize(LF); itLF.More(); itLF.Next()) {
-    const TopoDS_Face&   F = TopoDS::Face(itLF.Value());
-    Standard_Real CurOffset = myOffset;
-    if (myFaceOffset.IsBound(F)) CurOffset = myFaceOffset(F);
-    BRepOffset_Offset    OF(F,CurOffset,EdgeTgt,OffsetOutside,myJoin);
-    TopTools_ListOfShape Let;
-    myAnalyse.Edges(F,BRepOffset_Tangent,Let);
-    TopTools_ListIteratorOfListOfShape itl(Let);
-    
-    for ( ; itl.More(); itl.Next()) {
-      const TopoDS_Edge& Cur = TopoDS::Edge(itl.Value());
-      if ( !EdgeTgt.IsBound(Cur)) {
-        TopoDS_Shape aLocalShape = OF.Generated(Cur);
-        const TopoDS_Edge& OTE = TopoDS::Edge(aLocalShape);
-//        const TopoDS_Edge& OTE = TopoDS::Edge(OF.Generated(Cur));
-        EdgeTgt.Bind(Cur,OF.Generated(Cur));
-        TopoDS_Vertex V1,V2,OV1,OV2;
-        TopExp::Vertices (Cur,V1,V2);
-        TopExp::Vertices (OTE,OV1,OV2);      
-        TopTools_ListOfShape LE;
-        if (!EdgeTgt.IsBound(V1)) {
-          myAnalyse.Edges(V1,BRepOffset_Tangent,LE);
-          const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V1);
-          if (LE.Extent() == LA.Extent())
-            EdgeTgt.Bind(V1,OV1);
-        }
-        if (!EdgeTgt.IsBound(V2)) {
-          LE.Clear();
-          myAnalyse.Edges(V2,BRepOffset_Tangent,LE);
-          const TopTools_ListOfShape& LA =myAnalyse.Ancestors(V2);
-          if (LE.Extent() == LA.Extent())
-              EdgeTgt.Bind(V2,OV2);
-        }
-      }
-    }
-    MapSF.Bind(F,OF);
-  }
+  BRepOffset_DataMapOfShapeOffset MapSF;
+  MakeOffsetFaces(MapSF);
   //--------------------------------------------------------
   // Construction of tubes on edge.
   //--------------------------------------------------------
@@ -2958,13 +2387,8 @@ void BRepOffset_MakeOffset::MakeLoops(TopTools_IndexedMapOfShape& Modif)
       LF.Append(Modif(i));
   }
   //
-  if ((myJoin == GeomAbs_Intersection) && myInter) {
-    TopTools_ListOfShape aLFailed;
-    TopTools_IndexedDataMapOfShapeListOfShape anOr;
-    BuildSplitsOfFaces(LF, myAsDes, anOr, myImageOffset, aLFailed, Standard_True);
-    if (aLFailed.Extent()) {
-      myMakeLoops.Build(aLFailed, myAsDes, myImageOffset);
-    }
+  if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
+    BuildSplitsOfTrimmedFaces(LF, myAsDes, myImageOffset);
   }
   else {
     myMakeLoops.Build(LF,myAsDes,myImageOffset);
@@ -3013,13 +2437,8 @@ void BRepOffset_MakeOffset::MakeFaces(TopTools_IndexedMapOfShape& /*Modif*/)
     }
   }
   //
-  if ((myJoin == GeomAbs_Intersection) && myInter) {
-    TopTools_ListOfShape aLFailed;
-    TopTools_IndexedDataMapOfShapeListOfShape anOr;
-    BuildSplitsOfFaces(LOF, myAsDes, anOr, myImageOffset, aLFailed, Standard_True);
-    if (aLFailed.Extent()) {
-      myMakeLoops.BuildFaces(aLFailed, myAsDes, myImageOffset);
-    }
+  if ((myJoin == GeomAbs_Intersection) && myInter && myIsPlanar) {
+    BuildSplitsOfTrimmedFaces(LOF, myAsDes, myImageOffset);
   }
   else {
     myMakeLoops.BuildFaces(LOF,myAsDes,myImageOffset);
@@ -3515,21 +2934,20 @@ void BRepOffset_MakeOffset::MakeShells ()
   TopTools_ListIteratorOfListOfShape it(R);
   //
   for (; it.More(); it.Next()) {
+    const TopoDS_Shape& aF = it.Value();
+    //
     TopTools_ListOfShape Image;
-    myImageOffset.LastImage(it.Value(),Image);
+    myImageOffset.LastImage(aF,Image);
     TopTools_ListIteratorOfListOfShape it2(Image);
     for (; it2.More(); it2.Next()) {
-      const TopoDS_Shape& aF = it2.Value();
-      aLSF.Append(aF);
+      const TopoDS_Shape& aFIm = it2.Value();
+      aLSF.Append(aFIm);
       //
-      if (anOrigins.Contains(aF)) {
-        anOrigins.ChangeFromKey(aF).Append(it.Value());
-      }
-      else {
-        TopTools_ListOfShape aLOr;
-        aLOr.Append(it.Value());
-        anOrigins.Add(aF, aLOr);
+      TopTools_ListOfShape *pLOr = anOrigins.ChangeSeek(aFIm);
+      if (!pLOr) {
+        pLOr = &anOrigins(anOrigins.Add(aFIm, TopTools_ListOfShape()));
       }
+      pLOr->Append(aF);
     }
   }
   //
@@ -3547,141 +2965,27 @@ void BRepOffset_MakeOffset::MakeShells ()
     }
   }
   //
+  if (aLSF.IsEmpty()) {
+    return;
+  }
+  //
   Standard_Boolean bDone = Standard_False;
   if ((myJoin == GeomAbs_Intersection) && myInter &&
       !myThickening && myFaces.IsEmpty() &&
       IsSolid(myShape) && myIsPlanar) {
     //
-    // make shells using MakerVolume algorithm
-    Standard_Integer i, aNb;
-    TopTools_ListIteratorOfListOfShape aItLS, aItLS1;
-    BRep_Builder aBB;
-    //
-    BOPAlgo_MakerVolume aMV1;
-    aMV1.SetArguments(aLSF);
-    aMV1.SetIntersect(Standard_True);
-    aMV1.Perform();
-    //
-    bDone = (aMV1.ErrorStatus() == 0);
+    TopoDS_Shape aShells;
+    bDone = BuildShellsCompleteInter(aLSF, anOrigins, myImageOffset, aShells);
     if (bDone) {
-      UpdateHistory(aLSF, aMV1, myImageOffset);
-      //
-      TopoDS_Shape aResult = aMV1.Shape();
-      //
-      TopTools_IndexedMapOfShape aMFResult;
-      TopExp::MapShapes(aResult, TopAbs_FACE, aMFResult);
-      //
-      // check the result
-      Standard_Boolean bGood = Standard_True;
-      if (myRemoveInvalidFaces) {
-        BOPCol_ListIteratorOfListOfShape aItLSF(aLSF);
-        for (; aItLSF.More(); aItLSF.Next()) {
-          const TopoDS_Shape& aFx = aItLSF.Value();
-          if (!aMFResult.Contains(aFx)) {
-            const TopTools_ListOfShape& aLFMx = aMV1.Modified(aFx);
-            if (aLFMx.IsEmpty()) {
-              bGood = Standard_False;
-              break;
-            }
-          }
-        }
-      }
-      //
-      TopoDS_Compound aShells;
-      aBB.MakeCompound(aShells);
-      //
-      if (!bGood) {
-        myOffsetShape = aShells;
-      }
-      else {
-        if (aResult.ShapeType() == TopAbs_COMPOUND) {
-          // collect faces attached to only one solid
-          BOPCol_IndexedDataMapOfShapeListOfShape aMFS;
-          BOPCol_ListOfShape aLSF2;
-          //
-          BOPTools::MapShapesAndAncestors(aResult, TopAbs_FACE, TopAbs_SOLID, aMFS);
-          aNb = aMFS.Extent();
-          bDone = (aNb > 0);
-          //
-          if (bDone) {
-            for (i = 1; i <= aNb; ++i) {
-              const BOPCol_ListOfShape& aLSx = aMFS(i);
-              if (aLSx.Extent() == 1) {
-                const TopoDS_Shape& aFx = aMFS.FindKey(i);
-                aLSF2.Append(aFx);
-              }
-            }
-            //
-            // make solids from the new list
-            BOPAlgo_MakerVolume aMV2;
-            //
-            aMV2.SetArguments(aLSF2);
-            aMV2.SetIntersect(Standard_False);
-            //
-            aMV2.Perform();
-            bDone = (aMV2.ErrorStatus() == 0);
-            if (bDone) {
-              aResult = aMV2.Shape();
-              if (aResult.ShapeType() == TopAbs_COMPOUND) {
-                BOPCol_ListOfShape aLSF3;
-                //
-                TopExp_Explorer aExp(aResult, TopAbs_FACE);
-                for (; aExp.More(); aExp.Next()) {
-                  const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
-                  //
-                  // check orientation
-                  if (!anOrigins.Contains(aF)) {
-                    aLSF3.Append(aF);
-                    continue;
-                  }
-                  //
-                  const TopTools_ListOfShape& aLFOr = anOrigins.FindFromKey(aF);
-                  aItLS.Initialize(aLFOr);
-                  for (; aItLS.More(); aItLS.Next()) {
-                    const TopoDS_Face& aFOr = *(TopoDS_Face*)&aItLS.Value();
-                    //
-                    if (CheckNormals(aF, aFOr)) {
-                      aLSF3.Append(aF);
-                      break;
-                    }
-                  }
-                }
-                //
-                // make solid containing most outer faces
-                BOPAlgo_MakerVolume aMV3;
-                //
-                aMV3.SetArguments(aLSF3);
-                aMV3.SetIntersect(Standard_False);
-                //
-                aMV3.Perform();
-                bDone = (aMV3.ErrorStatus() == 0);
-                if (bDone) {
-                  aResult = aMV3.Shape();
-                }
-              }
-            }
-          }
-        }
-        //
-        TopExp_Explorer aExp(aResult, TopAbs_SHELL);
-        bDone = aExp.More();
-        for (; aExp.More(); aExp.Next()) {
-          const TopoDS_Shell& aSh = *(TopoDS_Shell*)&aExp.Current();
-          aBB.Add(aShells, aSh);
-        }
-        myOffsetShape = aShells;
-      }
+      myOffsetShape = aShells;
     }
   }
   //
   if (!bDone) {
     BRepTools_Quilt Glue;
-    BOPCol_ListIteratorOfListOfShape aItLS;
-    //
-    aItLS.Initialize(aLSF);
+    BOPCol_ListIteratorOfListOfShape aItLS(aLSF);
     for (; aItLS.More(); aItLS.Next()) {
-      const TopoDS_Shape& aF = aItLS.Value();
-      Glue.Add(aF);
+      Glue.Add(aItLS.Value());
     }
     myOffsetShape = Glue.Shells();
   }
@@ -3698,7 +3002,7 @@ void BRepOffset_MakeOffset::MakeShells ()
         aS.Closed(Standard_True);
       }
     }
-  }               
+  }
 }
 
 //=======================================================================
@@ -3803,7 +3107,7 @@ void BRepOffset_MakeOffset::MakeSolid ()
 //=======================================================================
 
 void BRepOffset_MakeOffset::SelectShells ()
-{  
+{
   TopTools_MapOfShape FreeEdges;
   TopExp_Explorer exp(myShape,TopAbs_EDGE);
   //-------------------------------------------------------------
@@ -4132,6 +3436,9 @@ void CorrectSolid(TopoDS_Solid& theSol, TopTools_ListOfShape& theSolList)
     aVols.Append(aVProps.Mass());
   }
   //
+  if (Abs(anOuterVol) < Precision::Confusion()) {
+    return;
+  }
   if(anOuterVol < 0.)
   {
     anOuterShell.Reverse();
@@ -4433,466 +3740,439 @@ void RemoveShapes(TopoDS_Shape& theS,
 }
 
 //=======================================================================
-//function : SortFaces
-//purpose  : 
+//function : UpdateHistory
+//purpose  : Updates the history information
 //=======================================================================
-void SortFaces(const TopTools_ListOfShape& theLIm, 
-               TopTools_ListOfShape& theLFImages,
-               const Standard_Boolean bKeepFirst)
+void UpdateHistory(const TopTools_ListOfShape& theLF,
+                   BOPAlgo_Builder& theGF,
+                   BRepAlgo_Image& theImage)
 {
-  Standard_Integer bKeep; // 1 - keep; -1 - remove
-  Standard_Boolean bFlag, bProceeded;
-  TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
-  TopTools_ListOfShape aLFKeep, aLFLeft, aLFTmp;
-  TopTools_MapOfShape aMV;
-  TopTools_ListIteratorOfListOfShape aItLF;
-  TopExp_Explorer aExp;
-  //
-  aLFLeft = theLIm;
-  //
-  bKeep = bKeepFirst ? 1 : -1;
-  for (;;) {
-    aLFTmp = aLFLeft;
-    //
-    aLFLeft.Clear();
-    aLFKeep.Clear();
-    aDMELF.Clear();
-    bProceeded = Standard_False;
-    //
-    // map list of images  edge - faces
-    aItLF.Initialize(aLFTmp);
-    for (; aItLF.More(); aItLF.Next()) {
-      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-      TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
-    }
-    //
-    // find images that have edge attached to only one face
-    aItLF.Initialize(aLFTmp);
-    for (; aItLF.More(); aItLF.Next()) {
-      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-      aExp.Init(aFIm, TopAbs_EDGE);
-      for (bFlag = Standard_False; aExp.More(); aExp.Next()) {
-        const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
-        const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE);
-        if (aLEF.Extent() == 1) {
-          TopoDS_Vertex aV1, aV2;
-          TopExp::Vertices(aE, aV1, aV2);
-          aMV.Add(aV1);
-          aMV.Add(aV2);
-          //
-          bFlag = Standard_True;
-        }
-      }
-      //
-      if (bFlag) {
-        aLFKeep.Append(aFIm);
-        bProceeded = Standard_True;
-      }
-      else {
-        aLFLeft.Append(aFIm);
-      }
-    }
-    //
-    // map shapes left for processing
-    aDMELF.Clear();
-    aLFTmp = aLFLeft;
-    aLFLeft.Clear();
-    //
-    aItLF.Initialize(aLFTmp);
-    for (; aItLF.More(); aItLF.Next()) {
-      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-      TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
-    }
-    //
-    // find outer edges and check if they touch the first part of edges
-    aItLF.Initialize(aLFTmp);
-    for (; aItLF.More(); aItLF.Next()) {
-      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-      aExp.Init(aFIm, TopAbs_EDGE);
-      for (bFlag = Standard_False; aExp.More() && !bFlag; aExp.Next()) {
-        const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
-        const TopTools_ListOfShape& aLEF = aDMELF.FindFromKey(aE);
-        if (aLEF.Extent() == 1) {
-          TopoDS_Vertex aV1, aV2;
-          TopExp::Vertices(aE, aV1, aV2);
-          //
-          bFlag = aMV.Contains(aV1) || aMV.Contains(aV2);
-        }
-      }
-      //
-      if (bFlag) {
-        aLFKeep.Append(aFIm);
-        bProceeded = Standard_True;
+  TopTools_ListIteratorOfListOfShape aIt(theLF);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aF = aIt.Value();
+    const TopTools_ListOfShape& aLFIm = theGF.Modified(aF);
+    if (aLFIm.Extent()) {
+      if (theImage.HasImage(aF)) {
+        theImage.Add(aF, aLFIm);
       }
       else {
-        aLFLeft.Append(aFIm);
-      }
-    }
-    //
-    if (bKeep == 1) {
-      // aLFKeep should be kept
-      // aLFLeft left for further processing
-      aItLF.Initialize(aLFKeep);
-      for (; aItLF.More(); aItLF.Next()) {
-        const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-        theLFImages.Append(aFIm);
+        theImage.Bind(aF, aLFIm);
       }
     }
-    //
-    if (aLFLeft.IsEmpty()) {
-      break;
-    }
-    //
-    bKeep *= -1;
-    //
-    if (!bProceeded) {
-      break;
-    }
   }
 }
 
 //=======================================================================
-//function : FindShape
+//function : IntersectEdges
 //purpose  : 
 //=======================================================================
-Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
-                           const TopoDS_Shape& theSWhere,
-                           TopoDS_Shape& theRes)
+void BRepOffset_MakeOffset::IntersectEdges(const TopoDS_Shape& theShape,
+                                           BRepOffset_DataMapOfShapeOffset& theMapSF,
+                                           TopTools_DataMapOfShapeShape& theMES,
+                                           TopTools_DataMapOfShapeShape& theBuild,
+                                           Handle(BRepAlgo_AsDes)& theAsDes,
+                                           Handle(BRepAlgo_AsDes)& theAsDes2d)
 {
-  Standard_Boolean bFound = Standard_False;
-  TopAbs_ShapeEnum aType = theSWhat.ShapeType();
-  TopExp_Explorer aExp(theSWhere, aType);
+  Standard_Real aTolF;
+  TopTools_IndexedDataMapOfShapeListOfShape aDMVV;
+  TopExp_Explorer aExp(theShape, TopAbs_FACE);
+  // intersect edges created from edges
+  TopTools_IndexedMapOfShape aMFV;
   for (; aExp.More(); aExp.Next()) {
-    const TopoDS_Shape& aS = aExp.Current();
-    if (aS.IsSame(theSWhat)) {
-      theRes = aS;
-      bFound = Standard_True;
-      break;
-    }
+    const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
+    aTolF = BRep_Tool::Tolerance(aF);
+    BRepOffset_Inter2d::ConnexIntByInt
+      (aF, theMapSF(aF), theMES, theBuild, theAsDes2d, myOffset, aTolF, aMFV, aDMVV);
   }
-  return bFound;
+  // intersect edges created from vertices
+  Standard_Integer i, aNbF = aMFV.Extent();
+  for (i = 1; i <= aNbF; ++i) {
+    const TopoDS_Face& aF = TopoDS::Face(aMFV(i));
+    aTolF = BRep_Tool::Tolerance(aF);
+    BRepOffset_Inter2d::ConnexIntByIntInVert
+      (aF, theMapSF(aF), theMES, theBuild, theAsDes, theAsDes2d, aTolF, aDMVV);
+  }
+  //
+  // fuse vertices on edges
+  BRepOffset_Inter2d::FuseVertices(aDMVV, theAsDes2d);
 }
 
 //=======================================================================
-//function : UpdateOrigins
+//function : TrimEdges
 //purpose  : 
 //=======================================================================
-void UpdateOrigins(TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-                   BOPAlgo_Builder& theGF)
+void TrimEdges(const TopoDS_Shape& theShape,
+               const Standard_Real theOffset,
+               BRepOffset_DataMapOfShapeOffset& theMapSF,
+               TopTools_DataMapOfShapeShape& theMES,
+               TopTools_DataMapOfShapeShape& theBuild,
+               Handle(BRepAlgo_AsDes)& theAsDes,
+               Handle(BRepAlgo_AsDes)& theAsDes2d,
+               TopTools_IndexedMapOfShape& theNewEdges,
+               TopTools_DataMapOfShapeShape& theETrimEInf,
+               TopTools_DataMapOfShapeListOfShape& theEdgesOrigins)
 {
-  TopTools_ListOfShape aLSTmp;
-  TopTools_MapOfShape aMFence;
-  BOPCol_ListIteratorOfListOfShape aItA;
-  TopTools_ListIteratorOfListOfShape aIt, aIt1;
+  TopExp_Explorer Exp,Exp2,ExpC;
+  TopoDS_Shape    NE;
+  TopoDS_Edge     TNE;
+  TopoDS_Face     NF;
   //
-  const BOPCol_ListOfShape& aLSU = theGF.Arguments();
-  aItA.Initialize(aLSU);
-  for (; aItA.More(); aItA.Next()) {
-    const TopoDS_Shape& aS = aItA.Value();
-    //
-    if (!theOrigins.Contains(aS)) {
-      continue;
+  for (Exp.Init(theShape,TopAbs_FACE) ; Exp.More(); Exp.Next()) {
+    const TopoDS_Face& FI = TopoDS::Face(Exp.Current());
+    NF = theMapSF(FI).Face();
+    if (theMES.IsBound(NF)) {
+      NF = TopoDS::Face(theMES(NF));
     }
     //
-    const TopTools_ListOfShape& aLSIm = theGF.Modified(aS);
-    if (aLSIm.IsEmpty()) {
-      continue;
-    }
+    TopTools_MapOfShape View;
+    TopTools_IndexedMapOfShape VEmap;
+    Standard_Integer i, aNb;
     //
-    const TopTools_ListOfShape& aLS = theOrigins.FindFromKey(aS);
-    //      
-    aIt.Initialize(aLSIm);
-    for (; aIt.More(); aIt.Next()) {
-      const TopoDS_Shape& aSIm = aIt.Value();
-      //
-      if (!theOrigins.Contains(aSIm)) {
-        theOrigins.Add(aSIm, aLS);
+    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_EDGE  , VEmap);
+    TopExp::MapShapes(FI.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap);
+    //
+    aNb = VEmap.Extent();
+    for (i = 1; i <= aNb; ++i) {
+      const TopoDS_Shape& aS = VEmap(i);
+      if (!View.Add(aS)) {
         continue;
       }
       //
-      aMFence.Clear();
-      //
-      TopTools_ListOfShape& aLS1 = theOrigins.ChangeFromKey(aSIm);
-      aLSTmp.Assign(aLS1);
-      //
-      aLS1.Clear();
-      aIt1.Initialize(aLSTmp);
-      for (; aIt1.More(); aIt1.Next()) {
-        const TopoDS_Shape& aS1 = aIt1.Value();
-        if (aMFence.Add(aS1)) {
-          aLS1.Append(aS1);
+      if (theBuild.IsBound(aS)) {
+        NE = theBuild(aS);
+        // keep connection to original edges
+        ExpC.Init(NE, TopAbs_EDGE);
+        for (; ExpC.More(); ExpC.Next()) {
+          const TopoDS_Edge& NEC = TopoDS::Edge(ExpC.Current());
+          TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NEC);
+          if (!pLEOr) {
+            pLEOr = theEdgesOrigins.Bound(NEC, TopTools_ListOfShape());
+          }
+          AppendToList(*pLEOr, aS);
         }
-      }
-      //
-      aIt1.Initialize(aLS);
-      for (; aIt1.More(); aIt1.Next()) {
-        const TopoDS_Shape& aS1 = aIt1.Value();
-        if (aMFence.Add(aS1)) {
-          aLS1.Append(aS1);
+        // trim edges
+        if (NE.ShapeType() == TopAbs_EDGE) {
+          if (theNewEdges.Add(NE)) {
+            TrimEdge (TopoDS::Edge(NE),theAsDes2d,theAsDes, theETrimEInf);
+          }
+        }
+        else {
+          //------------------------------------------------------------
+          // The Intersections are on several edges.
+          // The pieces without intersections with neighbors  
+          // are removed from AsDes.
+          //------------------------------------------------------------
+          for (ExpC.Init(NE,TopAbs_EDGE); ExpC.More(); ExpC.Next()) {
+            TopoDS_Edge NEC = TopoDS::Edge(ExpC.Current());
+            if (theNewEdges.Add(NEC)) {
+              if (!theAsDes2d->Descendant(NEC).IsEmpty()) {
+                TrimEdge (NEC,theAsDes2d, theAsDes, theETrimEInf);
+              }
+              else {
+                if (theAsDes->HasAscendant(NEC)) {
+                  theAsDes->Remove(NEC);
+                }
+              }
+            }
+          }
         }
       }
+      else {
+        if (aS.ShapeType() != TopAbs_EDGE) {
+          continue;
+        }
+        //
+        NE = theMapSF(FI).Generated(aS);
+        //// modified by jgv, 19.12.03 for OCC4455 ////
+        NE.Orientation(aS.Orientation());
+        //
+        TopTools_ListOfShape* pLEOr = theEdgesOrigins.ChangeSeek(NE);
+        if (!pLEOr) {
+          pLEOr = theEdgesOrigins.Bound(NE, TopTools_ListOfShape());
+        }
+        AppendToList(*pLEOr, aS);
+        //
+        if (theMES.IsBound(NE)) {
+          NE = theMES(NE);
+          NE.Orientation(aS.Orientation());
+          if (theNewEdges.Add(NE)) {
+            TrimEdge (TopoDS::Edge(NE), theAsDes2d, theAsDes, theETrimEInf);
+          } 
+        }
+        else {
+          TopoDS_Edge& anEdge = TopoDS::Edge(NE);
+          BRepAdaptor_Curve aBAC(anEdge);
+          if (aBAC.GetType() == GeomAbs_Line) {
+            TopoDS_Edge aNewEdge;
+            BRepOffset_Inter2d::ExtentEdge(anEdge, aNewEdge, theOffset);
+            theETrimEInf.Bind(anEdge, aNewEdge);
+          }
+        }
+        theAsDes->Add(NF,NE);
+      } 
     }
   }
 }
 
 //=======================================================================
-//function : ProcessMicroEdge
-//purpose  : 
+//function : TrimEdge
+//purpose  : Trim the edge of the largest of descendants in AsDes2d.
+//           Order in AsDes two vertices that have trimmed the edge.
 //=======================================================================
-Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
-                                  const Handle(IntTools_Context)& theCtx)
+void TrimEdge(TopoDS_Edge&                  NE,
+              const Handle(BRepAlgo_AsDes)& AsDes2d,
+              Handle(BRepAlgo_AsDes)& AsDes,
+              TopTools_DataMapOfShapeShape& theETrimEInf)
 {
-  TopoDS_Vertex aV1, aV2;
-  TopExp::Vertices(theEdge, aV1, aV2);
-  Standard_Boolean bNull = aV1.IsNull() || aV2.IsNull();
-  if (bNull) {
-    return Standard_False;
-  }
+  TopoDS_Edge aSourceEdge;
+  TopoDS_Vertex V1,V2;
+  Standard_Real aT1, aT2;
   //
-  Standard_Boolean bMicro;
-  bMicro = BOPTools_AlgoTools::IsMicroEdge(theEdge, theCtx);
-  if (bMicro) {
-    BRepAdaptor_Curve aBAC(theEdge);
-    if (aBAC.GetType() == GeomAbs_Line) {
-      BRep_Builder aBB;
-      Standard_Real aLen = CPnts_AbscissaPoint::Length(aBAC);
+  TopExp::Vertices(NE, V1, V2);
+  BRep_Tool::Range(NE, aT1, aT2);
+  //
+  BOPTools_AlgoTools::MakeSplitEdge(NE, V1, aT1, V2, aT2, aSourceEdge);
+  //
+  //
+  Standard_Real aSameParTol = Precision::Confusion();
+  
+  Standard_Real U = 0.;
+  Standard_Real UMin =  Precision::Infinite();
+  Standard_Real UMax = -UMin;
+
+  const TopTools_ListOfShape& LE = AsDes2d->Descendant(NE);
+  //
+  Standard_Boolean bTrim = Standard_False;
+  //
+  if (LE.Extent() > 1) {
+    TopTools_ListIteratorOfListOfShape it (LE);
+    for (; it.More(); it.Next()) {
+      TopoDS_Vertex V = TopoDS::Vertex(it.Value());
+      if (NE.Orientation() == TopAbs_REVERSED)
+        V.Reverse();
+      //V.Orientation(TopAbs_INTERNAL);
+      if (!FindParameter(V, NE, U)) {
+        Standard_Real f, l;
+        Handle(Geom_Curve) theCurve = BRep_Tool::Curve(NE, f, l);
+        gp_Pnt thePoint = BRep_Tool::Pnt(V);
+        GeomAPI_ProjectPointOnCurve Projector(thePoint, theCurve);
+        if (Projector.NbPoints() == 0)
+          Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge no projection");
+        U = Projector.LowerDistanceParameter();
+      }
+      if (U < UMin) {
+        UMin = U; V1   = V;
+      }
+      if (U > UMax) {
+        UMax = U; V2   = V;
+      }
+    }
+    //
+    if (V1.IsNull() || V2.IsNull()) {
+      Standard_ConstructionError::Raise("BRepOffset_MakeOffset::TrimEdge");
+    }
+    if (!V1.IsSame(V2)) {
+      NE.Free( Standard_True );
+      BRep_Builder B;
+      TopAbs_Orientation Or = NE.Orientation();
+      NE.Orientation(TopAbs_FORWARD);
+      TopoDS_Vertex VF,VL;
+      TopExp::Vertices (NE,VF,VL);
+      B.Remove(NE,VF);
+      B.Remove(NE,VL);
+      B.Add  (NE,V1.Oriented(TopAbs_FORWARD));
+      B.Add  (NE,V2.Oriented(TopAbs_REVERSED));
+      B.Range(NE,UMin,UMax);
+      NE.Orientation(Or);
+      AsDes->Add(NE,V1.Oriented(TopAbs_FORWARD));
+      AsDes->Add(NE,V2.Oriented(TopAbs_REVERSED));
+      BRepLib::SameParameter(NE, aSameParTol, Standard_True);
       //
-      aBB.UpdateVertex(aV1, aLen/2.);
-      aBB.UpdateVertex(aV2, aLen/2.);
+      bTrim = Standard_True;
     }
   }
   //
-  return bMicro;
+  if (!bTrim) {
+    BRepAdaptor_Curve aBAC(NE);
+    if (aBAC.GetType() == GeomAbs_Line) {
+      if (AsDes->HasAscendant(NE)) {
+        AsDes->Remove(NE);
+      }
+    }
+  }
+  else
+  {
+    if (!theETrimEInf.IsBound(NE)) {
+      theETrimEInf.Bind(NE, aSourceEdge);
+    }
+  }
 }
 
 //=======================================================================
-//function : ComputeBiNormal
+//function : GetEnlargedFaces
 //purpose  : 
 //=======================================================================
-Standard_Boolean ComputeBiNormal(const TopoDS_Face& theF,
-                                 const TopoDS_Edge& theE,
-                                 gp_Dir& theDB)
+void GetEnlargedFaces(const TopoDS_Shape& theShape,
+                      const BRepOffset_DataMapOfShapeOffset& theMapSF,
+                      const TopTools_DataMapOfShapeShape& theMES,
+                      TopTools_DataMapOfShapeShape& theFacesOrigins,
+                      BRepAlgo_Image& theImage,
+                      TopTools_ListOfShape& theLSF)
 {
-  Standard_Boolean bDone = Standard_False;
-  Standard_Real aT1, aT2, aTm;
+  TopExp_Explorer aExp(theShape, TopAbs_FACE);
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Shape& FI  = aExp.Current();
+    const TopoDS_Shape& OFI = theMapSF(FI).Face();
+    if (theMES.IsBound(OFI)) {
+      const TopoDS_Face& aLocalFace = TopoDS::Face(theMES(OFI));
+      theLSF.Append(aLocalFace);
+      theImage.SetRoot(aLocalFace);
+      //
+      theFacesOrigins.Bind(aLocalFace, FI);
+    }
+  }
+}
+
+//=======================================================================
+//function : BuildShellsCompleteInter
+//purpose  : Make the shells from list of faces using MakerVolume algorithm.
+//           In case there will be more than just one solid, it will be
+//           rebuilt using only outer faces.
+//=======================================================================
+Standard_Boolean BuildShellsCompleteInter(const BOPCol_ListOfShape& theLF,
+                                          const BOPCol_IndexedDataMapOfShapeListOfShape& theOrigins,
+                                          BRepAlgo_Image& theImage,
+                                          TopoDS_Shape& theShells)
+{
+  // make solids
+  BOPAlgo_MakerVolume aMV1;
+  aMV1.SetArguments(theLF);
+  // we need to intersect the faces to process the tangential faces
+  aMV1.SetIntersect(Standard_True);
+  aMV1.Perform();
   //
-  const Handle(Geom2d_Curve)& aC2d = 
-    BRep_Tool::CurveOnSurface(theE, theF, aT1, aT2);
-  if (aC2d.IsNull()) {
+  Standard_Boolean bDone = (aMV1.ErrorStatus() == 0);
+  if (!bDone) {
     return bDone;
   }
   //
-  gp_Pnt2d aP2dNear;
-  gp_Pnt aP, aPNear;
-  //
-  const Handle(Geom_Curve)& aC3d = 
-    BRep_Tool::Curve(theE, aT1, aT2);
+  UpdateHistory(theLF, aMV1, theImage);
   //
-  aTm = (aT1 + aT2) * 0.5;
-  aP = aC3d->Value(aTm);
+  const TopoDS_Shape& aResult1 = aMV1.Shape();
+  if (aResult1.ShapeType() == TopAbs_SOLID) {
+    // result is the alone solid, nothing to do
+    return GetSubShapes(aResult1, TopAbs_SHELL, theShells);
+  }
   //
-  BOPTools_AlgoTools3D::PointNearEdge(theE, theF, aTm, 1.e-5, aP2dNear, aPNear);
+  // it is necessary to rebuild the solids, avoiding internal faces
   //
-  gp_Vec aVB(aP, aPNear);
-  theDB = gp_Dir(aVB);
-  return !bDone;
-}
-
-//=======================================================================
-//function : CheckBiNormals
-//purpose  : 
-//=======================================================================
-Standard_Boolean CheckBiNormals
-  (const TopoDS_Face& aFIm,
-   const TopoDS_Face& aFOr,
-   const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-   const TopTools_MapOfShape& theMFence,
-   Standard_Boolean& bKeep,
-   Standard_Boolean& bRemove,
-   const Standard_Boolean RemoveInvalidFaces)
-{
-  bKeep = Standard_True;
-  bRemove = Standard_False;
-
-  Standard_Boolean bChecked;
-  Standard_Integer aNbEdgesChecked;
-  Standard_Real anAngle;
-  TopTools_IndexedMapOfShape aMEInv;
+  // map faces to solids
+  TopTools_IndexedDataMapOfShapeListOfShape aDMFS;
+  TopExp::MapShapesAndAncestors(aResult1, TopAbs_FACE, TopAbs_SOLID, aDMFS);
   //
-  aNbEdgesChecked = 0;
+  Standard_Integer i, aNb = aDMFS.Extent();
+  bDone = (aNb > 0);
+  if (!bDone) {
+    // unable to build any solid
+    return bDone;
+  }
   //
-  const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
-  TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
-  for (; aExp.More(); aExp.Next()) {
-    const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
-    //
-    if (BRep_Tool::Degenerated(aEIm)) {
-      continue;
-    }
-    //
-    if (!theOrigins.Contains(aEIm)) {
-      continue;
-    }
-    //
-    const TopTools_ListOfShape& aLEOr = theOrigins.FindFromKey(aEIm);
-    const TopoDS_Shape& aSOr = aLEOr.First();
-    if (aSOr.ShapeType() != TopAbs_EDGE) {
-      continue;
-    }
-    //
-    if (aLEOr.Extent() > 1) {
-      TopTools_MapOfShape aME, aMV;
-      Standard_Integer aNbE, aNbV;
-      //
-      TopTools_ListIteratorOfListOfShape aItLS(aLEOr);
-      for (; aItLS.More(); aItLS.Next()) {
-        const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&aItLS.Value();
-        aME.Add(aEOr);
-        //
-        TopExp_Explorer aExpE(aEOr, TopAbs_VERTEX);
-        for (; aExpE.More(); aExpE.Next()) {
-          const TopoDS_Shape& aV = aExpE.Current();
-          aMV.Add(aV);
-        }
-      }
-      //
-      aNbV = aMV.Extent();
-      aNbE = aME.Extent();
-      //
-      if ((aNbE > 1) && (aNbV == 2*aNbE)) {
-        continue;
-      }
-    }
-    //
-    if (!RemoveInvalidFaces) {
-      if (theMFence.Contains(aEIm)) {
-        bChecked = Standard_True;
-        bKeep = Standard_True;
-        bRemove = Standard_False;
-        return bChecked;
-      }
-    }
-    //
-    const TopoDS_Edge& aEOr = *(TopoDS_Edge*)&aLEOr.First();
-    //
-    TopoDS_Edge aEOrF;
-    if (!FindShape(aEOr, aFOr, aEOrF)) {
-      continue;
-    }
-    //
-    // compute bi-normal for face aFIm on the edge aEIm
-    gp_Dir aDB1;
-    if (!ComputeBiNormal(aFIm, aEIm, aDB1)) {
-      continue;
-    }
-    //
-    // compute bi-normal for face aFOr on the edge aEOrF
-    gp_Dir aDB2;
-    if (!ComputeBiNormal(aFOr, aEOrF, aDB2)) {
-      continue;
-    }
-    //
-    ++aNbEdgesChecked;
-    //
-    anAngle = aDB1.Angle(aDB2);
-    if (Abs(anAngle - M_PI) < 1.e-4) {
-      aMEInv.Add(aEIm);
+  // get faces attached to only one solid
+  BOPCol_ListOfShape aLF2;
+  for (i = 1; i <= aNb; ++i) {
+    const TopTools_ListOfShape& aLS = aDMFS(i);
+    if (aLS.Extent() == 1) {
+      const TopoDS_Shape& aF = aDMFS.FindKey(i);
+      aLF2.Append(aF);
     }
   }
   //
-  bChecked = (aNbEdgesChecked > 0);
-  if (!bChecked) {
-    return bChecked;
+  // make solids from the new list
+  BOPAlgo_MakerVolume aMV2;
+  aMV2.SetArguments(aLF2);
+  // no need to intersect this time
+  aMV2.SetIntersect(Standard_False);
+  aMV2.Perform();
+  bDone = (aMV2.ErrorStatus() == 0);
+  if (!bDone) {
+    return bDone;
   }
   //
-  // decide whether to remove the split face or not
-  //
-  Standard_Integer  aNb = aMEInv.Extent();
-  if (aNb == 0) {
-    return bChecked;
+  const TopoDS_Shape& aResult2 = aMV2.Shape();
+  if (aResult2.ShapeType() == TopAbs_SOLID) {
+    return GetSubShapes(aResult2, TopAbs_SHELL, theShells);
   }
   //
-  if (aNb == aNbEdgesChecked) {
-    bKeep = Standard_False;
-    bRemove = Standard_True;
+  TopExp_Explorer aExp(aResult2, TopAbs_FACE);
+  bDone = aExp.More();
+  if (!bDone) {
+    return bDone;
   }
   //
-  if (!bRemove) {
-    for (Standard_Integer i = 1; i <= aNb; ++i) {
-      const TopoDS_Shape& aE = aMEInv(i);
-      if (theMFence.Contains(aE)) {
-        bKeep = Standard_False;
-        bRemove = Standard_True;
+  // the result is non-manifold - resolve it comparing normals
+  // directions of the offset faces and original faces
+  BOPCol_ListOfShape aLF3;
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
+    //
+    // check orientation
+    if (!theOrigins.Contains(aF)) {
+      aLF3.Append(aF);
+      continue;
+    }
+    //
+    const TopTools_ListOfShape& aLFOr = theOrigins.FindFromKey(aF);
+    TopTools_ListIteratorOfListOfShape aItLF(aLFOr);
+    for (; aItLF.More(); aItLF.Next()) {
+      const TopoDS_Face& aFOr = TopoDS::Face(aItLF.Value());
+      if (CheckNormals(aF, aFOr)) {
+        aLF3.Append(aF);
         break;
       }
     }
   }
   //
-  return bChecked;
+  // make solid from most outer faces with correct normal direction
+  BOPAlgo_MakerVolume aMV3;
+  aMV3.SetArguments(aLF3);
+  aMV3.SetIntersect(Standard_False);
+  aMV3.Perform();
+  bDone = (aMV3.ErrorStatus() == 0);
+  if (!bDone) {
+    return bDone;
+  }
+  //
+  const TopoDS_Shape& aResult3 = aMV3.Shape();
+  return GetSubShapes(aResult3, TopAbs_SHELL, theShells);
 }
 
 //=======================================================================
-//function : CheckBiNormals
+//function : GetSubShapes
 //purpose  : 
 //=======================================================================
-void CheckBiNormals
-  (TopTools_ListOfShape&  theLFImages,
-   const TopoDS_Face& theF,
-   const TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-   TopTools_ListOfShape& theLFKeep,
-   const Standard_Boolean RemoveInvalidFaces)
+Standard_Boolean GetSubShapes(const TopoDS_Shape& theShape,
+                              const TopAbs_ShapeEnum theSSType,
+                              TopoDS_Shape& theResult)
 {
-  Standard_Boolean bChecked, bKeep, bRem;
-  Standard_Integer i, aNb;
-  TopTools_ListOfShape aLFKeep;
-  TopTools_MapOfShape aMEToKeep;
-  TopTools_IndexedDataMapOfShapeListOfShape aDMELF;
-  TopTools_ListIteratorOfListOfShape aItLF;
-  //
-  // collect outer edges
-  aItLF.Initialize(theLFImages);
-  for (; aItLF.More(); aItLF.Next()) {
-    const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-    TopExp::MapShapesAndAncestors(aFIm, TopAbs_EDGE, TopAbs_FACE, aDMELF);
-  }
-  //
-  aNb = aDMELF.Extent();
-  for (i = 1; i <= aNb; ++i) {
-    const TopTools_ListOfShape& aLF = aDMELF(i);
-    if (aLF.Extent() == 1) {
-      const TopoDS_Shape& aE = aDMELF.FindKey(i);
-      aMEToKeep.Add(aE);
-    }
+  TopExp_Explorer aExp(theShape, theSSType);
+  if (!aExp.More()) {
+    return Standard_False;
   }
   //
-  const TopoDS_Face& aFOr = *(TopoDS_Face*)&theOrigins.FindFromKey(theF).First();
+  TopoDS_Compound aResult;
+  BRep_Builder().MakeCompound(aResult);
   //
-  aItLF.Initialize(theLFImages);
-  for (; aItLF.More(); ) {
-    const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
-    //
-    bChecked = CheckBiNormals(aFIm, aFOr, theOrigins, aMEToKeep, bKeep, bRem, RemoveInvalidFaces);
-    //
-    if (bChecked) {
-      if (bRem) {
-        theLFImages.Remove(aItLF);
-      }
-      else {
-        if (bKeep) {
-          theLFKeep.Append(aFIm);
-        }
-        aItLF.Next();
-      }
-    }
-    else {
-      aItLF.Next();
-    }
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Shape& aSS = aExp.Current();
+    BRep_Builder().Add(aResult, aSS);
   }
+  theResult = aResult;
+  return Standard_True;
 }
 
 //=======================================================================
 //function : CheckNormals
-//purpose  : 
+//purpose  : Comparing normal directions of the faces
 //=======================================================================
 Standard_Boolean CheckNormals(const TopoDS_Face& theFIm,
                               const TopoDS_Face& theFOr)
@@ -4956,50 +4236,45 @@ Standard_Boolean CheckNormals(const TopoDS_Face& theFIm,
 }
 
 //=======================================================================
+//function : IsPlanar
+//purpose  : Checks if all the faces of the shape are planes
+//=======================================================================
+Standard_Boolean IsPlanar(const TopoDS_Shape& theS)
+{
+  TopExp_Explorer aExp(theS, TopAbs_FACE);
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
+    BRepAdaptor_Surface aBAS(aF, Standard_False);
+    if (aBAS.GetType() != GeomAbs_Plane) {
+      break;
+    }
+  }
+  return !aExp.More();
+}
+
+//=======================================================================
 //function : IsSolid
-//purpose  : Check if the shape is solid
+//purpose  : Checks if the shape is solid
 //=======================================================================
 Standard_Boolean IsSolid(const TopoDS_Shape& theS)
 {
   TopExp_Explorer aExp(theS, TopAbs_SOLID);
   return aExp.More();
 }
+
 //=======================================================================
-//function : UpdateHistory
-//purpose  : Updates the history information
+//function : AppendToList
+//purpose  : Add to a list only unique elements
 //=======================================================================
-void UpdateHistory(const TopTools_ListOfShape& theLF,
-                   BOPAlgo_Builder& theGF,
-                   BRepAlgo_Image& theImage)
+void AppendToList(TopTools_ListOfShape& theList,
+                  const TopoDS_Shape& theShape)
 {
-  TopTools_ListIteratorOfListOfShape aIt(theLF);
+  TopTools_ListIteratorOfListOfShape aIt(theList);
   for (; aIt.More(); aIt.Next()) {
-    const TopoDS_Shape& aF = aIt.Value();
-    const TopTools_ListOfShape& aLFIm = theGF.Modified(aF);
-    if (aLFIm.Extent()) {
-      if (theImage.HasImage(aF)) {
-        theImage.Add(aF, aLFIm);
-      }
-      else {
-        theImage.Bind(aF, aLFIm);
-      }
+    const TopoDS_Shape& aS = aIt.Value();
+    if (aS.IsSame(theShape)) {
+      return;
     }
   }
-}
-
-//=======================================================================
-//function : IsPlanar
-//purpose  : 
-//=======================================================================
-Standard_Boolean IsPlanar(const TopoDS_Shape& theS)
-{
-  Standard_Boolean bRet;
-  TopExp_Explorer aExp(theS, TopAbs_FACE);
-  for (bRet = Standard_True; aExp.More() && bRet; aExp.Next()) {
-    const TopoDS_Face& aF = *(TopoDS_Face*)&aExp.Current();
-    BRepAdaptor_Surface aBAS(aF, Standard_False);
-    bRet = (aBAS.GetType() == GeomAbs_Plane);
-  }
-  return bRet;
+  theList.Append(theShape);
 }
index 4af6b24..1fca4d4 100644 (file)
@@ -53,27 +53,25 @@ public:
   
   Standard_EXPORT BRepOffset_MakeOffset();
   
-  Standard_EXPORT BRepOffset_MakeOffset(const TopoDS_Shape& S, 
-                                        const Standard_Real Offset, 
-                                        const Standard_Real Tol, 
-                                        const BRepOffset_Mode Mode = BRepOffset_Skin, 
-                                        const Standard_Boolean Intersection = Standard_False, 
-                                        const Standard_Boolean SelfInter = Standard_False, 
-                                        const GeomAbs_JoinType Join = GeomAbs_Arc, 
+  Standard_EXPORT BRepOffset_MakeOffset(const TopoDS_Shape& S,
+                                        const Standard_Real Offset,
+                                        const Standard_Real Tol,
+                                        const BRepOffset_Mode Mode = BRepOffset_Skin,
+                                        const Standard_Boolean Intersection = Standard_False,
+                                        const Standard_Boolean SelfInter = Standard_False,
+                                        const GeomAbs_JoinType Join = GeomAbs_Arc,
                                         const Standard_Boolean Thickening = Standard_False,
-                                        const Standard_Boolean RemoveIntEdges = Standard_False,
-                                        const Standard_Boolean RemoveInvalidFaces = Standard_False);
-  
-  Standard_EXPORT void Initialize (const TopoDS_Shape& S, 
-                                   const Standard_Real Offset, 
-                                   const Standard_Real Tol, 
-                                   const BRepOffset_Mode Mode = BRepOffset_Skin, 
-                                   const Standard_Boolean Intersection = Standard_False, 
-                                   const Standard_Boolean SelfInter = Standard_False, 
-                                   const GeomAbs_JoinType Join = GeomAbs_Arc, 
+                                        const Standard_Boolean RemoveIntEdges = Standard_False);
+  
+  Standard_EXPORT void Initialize (const TopoDS_Shape& S,
+                                   const Standard_Real Offset,
+                                   const Standard_Real Tol,
+                                   const BRepOffset_Mode Mode = BRepOffset_Skin,
+                                   const Standard_Boolean Intersection = Standard_False,
+                                   const Standard_Boolean SelfInter = Standard_False,
+                                   const GeomAbs_JoinType Join = GeomAbs_Arc,
                                    const Standard_Boolean Thickening = Standard_False,
-                                   const Standard_Boolean RemoveIntEdges = Standard_False,
-                                   const Standard_Boolean RemoveInvalidFaces = Standard_False);
+                                   const Standard_Boolean RemoveIntEdges = Standard_False);
   
   Standard_EXPORT void Clear();
   
@@ -129,20 +127,13 @@ protected:
 
 private:
 
-  
   Standard_EXPORT void BuildOffsetByArc();
   
   Standard_EXPORT void BuildOffsetByInter();
 
-  //! Building splits of the offset faces by the section curves 
-  //! between the neighboring faces. 
-  Standard_EXPORT void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
-                                          const Handle(BRepAlgo_AsDes)& theAsDes,
-                                          TopTools_IndexedDataMapOfShapeListOfShape& theOrigins,
-                                          BRepAlgo_Image& theImage,
-                                          TopTools_ListOfShape& theLFailed,
-                                          const Standard_Boolean bLimited);
-  
+  //! Make Offset faces
+  Standard_EXPORT void MakeOffsetFaces(BRepOffset_DataMapOfShapeOffset& theMapSF);
+
   Standard_EXPORT void SelfInter (TopTools_MapOfShape& Modif);
   
   Standard_EXPORT void Intersection3D (BRepOffset_Inter3d& Inter);
@@ -177,7 +168,30 @@ private:
   //! Removes INTERNAL edges from the result
   Standard_EXPORT void RemoveInternalEdges();
 
-
+  //! Intersects edges
+  Standard_EXPORT void IntersectEdges (const TopoDS_Shape& theShape,
+                                       BRepOffset_DataMapOfShapeOffset& theMapSF,
+                                       TopTools_DataMapOfShapeShape& theMES,
+                                       TopTools_DataMapOfShapeShape& theBuild,
+                                       Handle(BRepAlgo_AsDes)& theAsDes,
+                                       Handle(BRepAlgo_AsDes)& theAsDes2d);
+
+  //! Building of the splits of the offset faces for mode Complete
+  //! and joint type Intersection. This method is an advanced alternative
+  //! for BRepOffset_MakeLoops::Build method.
+  //! Currently the Complete intersection mode is limited to work only on planar cases.
+  Standard_EXPORT void BuildSplitsOfExtendedFaces(const TopTools_ListOfShape& theLF,
+                                                  Handle(BRepAlgo_AsDes)& theAsDes,
+                                                  TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                                                  TopTools_DataMapOfShapeShape& theFacesOrigins,
+                                                  TopTools_DataMapOfShapeShape& theETrimEInf,
+                                                  BRepAlgo_Image& theImage);
+
+  //! Building of the splits of the already trimmed offset faces for mode Complete
+  //! and joint type Intersection.
+  Standard_EXPORT void BuildSplitsOfTrimmedFaces(const TopTools_ListOfShape& theLF,
+                                                 Handle(BRepAlgo_AsDes)& theAsDes,
+                                                 BRepAlgo_Image& theImage);
 
   Standard_Real myOffset;
   Standard_Real myTol;
@@ -188,7 +202,6 @@ private:
   GeomAbs_JoinType myJoin;
   Standard_Boolean myThickening;
   Standard_Boolean myRemoveIntEdges;
-  Standard_Boolean myRemoveInvalidFaces;
   TopTools_DataMapOfShapeReal myFaceOffset;
   TopTools_IndexedMapOfShape myFaces;
   BRepOffset_Analyse myAnalyse;
diff --git a/src/BRepOffset/BRepOffset_MakeOffset_1.cxx b/src/BRepOffset/BRepOffset_MakeOffset_1.cxx
new file mode 100644 (file)
index 0000000..68e9b0d
--- /dev/null
@@ -0,0 +1,5618 @@
+// Created on: 2016
+// Created by: Eugeny MALTCHIKOV
+// Copyright (c) 2016 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+
+// This is the implementation of the extension of the 3D offset algorithm
+// to work in mode Complete and Join Type Intersection.
+// Currently only the Planar cases are supported.
+
+
+#include <BRepOffset_MakeOffset.hxx>
+
+#include <Precision.hxx>
+#include <TopoDS.hxx>
+
+#include <BRepAlgo_AsDes.hxx>
+#include <BRepAlgo_Image.hxx>
+
+#include <BRep_Builder.hxx>
+#include <BRep_Tool.hxx>
+
+#include <BRepTools.hxx>
+
+#include <BRepAdaptor_Curve.hxx>
+
+#include <TopExp.hxx>
+#include <TopExp_Explorer.hxx>
+
+#include <TopTools_DataMapOfShapeInteger.hxx>
+
+#include <BRepOffset_Tool.hxx>
+
+#include <BRepClass3d_SolidClassifier.hxx>
+
+#include <BOPDS_DS.hxx>
+
+#include <BOPAlgo_PaveFiller.hxx>
+#include <BOPAlgo_Builder.hxx>
+#include <BOPAlgo_Section.hxx>
+#include <BOPAlgo_MakerVolume.hxx>
+
+#include <BOPCol_ListOfShape.hxx>
+#include <BOPCol_DataMapOfShapeShape.hxx>
+#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
+
+#include <BOPTools.hxx>
+#include <BOPTools_AlgoTools3D.hxx>
+#include <BOPTools_AlgoTools.hxx>
+
+#include <IntTools_Context.hxx>
+#include <IntTools_ShrunkRange.hxx>
+
+
+static
+  void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF,
+                             const Handle(BRepAlgo_AsDes)& theAsDes,
+                             TopTools_DataMapOfShapeListOfShape& theOEImages,
+                             TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                             TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                             Handle(IntTools_Context)& theCtx,
+                             TopTools_MapOfShape& theNewEdges,
+                             TopTools_DataMapOfShapeShape& theETrimEInf);
+
+static
+  Standard_Boolean GetEdges(const TopoDS_Face& theFace,
+                            const Handle(BRepAlgo_AsDes)& theAsDes,
+                            const TopTools_DataMapOfShapeListOfShape& theEImages,
+                            const TopTools_MapOfShape& theLastInvEdges,
+                            const TopTools_IndexedMapOfShape& theInvEdges,
+                            Handle(IntTools_Context)& theCtx,
+                            const TopTools_MapOfShape& theModifiedEdges,
+                            TopoDS_Shape& theEdges,
+                            TopTools_IndexedMapOfShape& theInv);
+
+static
+  void BuildSplitsOfFace(const TopoDS_Face& theFace,
+                         const TopoDS_Shape& theEdges,
+                         Standard_Boolean bTrimmed,
+                         TopTools_DataMapOfShapeShape& theOrigins,
+                         TopTools_ListOfShape& theLFImages);
+
+static
+  void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
+                          const TopTools_MapOfShape& theModifiedEdges,
+                          const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                          Handle(BRepAlgo_AsDes)& theAsDes,
+                          TopTools_DataMapOfShapeShape& theFacesOrigins,
+                          TopTools_DataMapOfShapeListOfShape& theOEImages,
+                          TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                          TopTools_MapOfShape& theLastInvEdges,
+                          TopTools_IndexedMapOfShape& theEdgesToAvoid,
+                          TopTools_IndexedMapOfShape& theInvEdges,
+                          TopTools_IndexedMapOfShape& theValidEdges,
+                          TopTools_MapOfShape& theInvertedEdges,
+                          TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
+                          TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                          TopTools_DataMapOfShapeShape& theArtInvFaces,
+                          TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                          TopoDS_Shape& theSolids,
+                          TopTools_DataMapOfShapeListOfShape& theSSInterfs);
+
+static 
+  void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, 
+                             const TopTools_MapOfShape& theModifiedEdges,
+                             TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                             TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                             TopTools_DataMapOfShapeShape& theFacesOrigins,
+                             TopTools_DataMapOfShapeListOfShape& theOEImages,
+                             TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                             TopTools_MapOfShape& theLastInvEdges,
+                             TopTools_IndexedMapOfShape& theEdgesToAvoid,
+                             TopTools_MapOfShape& theVertsToAvoid,
+                             TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
+                             TopTools_IndexedMapOfShape& theValidEdges,
+                             TopTools_DataMapOfShapeShape& theETrimEInf,
+                             Handle(BRepAlgo_AsDes)& theAsDes);
+
+static 
+  Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF,
+                                     const TopTools_ListOfShape& theLFImages,
+                                     const TopoDS_Shape& theCE,
+                                     const TopTools_IndexedMapOfShape& theMapEInv,
+                                     const TopTools_DataMapOfShapeListOfShape& theOEImages,
+                                     TopTools_MapOfShape& theMENInv,
+                                     Handle(BRepAlgo_AsDes)& theAsDes);
+
+static
+  void FindInvalidEdges(const TopoDS_Face& theF,
+                        const TopTools_ListOfShape& theLFImages,
+                        const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                        const TopTools_DataMapOfShapeShape& theFacesOrigins,
+                        const TopTools_DataMapOfShapeListOfShape& theOEImages,
+                        const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                        TopTools_IndexedMapOfShape& theInvEdges,
+                        TopTools_IndexedMapOfShape& theValidEdges,
+                        TopTools_DataMapOfShapeListOfShape& theDMFLVE,
+                        TopTools_DataMapOfShapeListOfShape& theDMFLNE,
+                        TopTools_DataMapOfShapeListOfShape& theDMFLIE,
+                        TopTools_DataMapOfShapeListOfShape& theDMFLVIE,
+                        TopTools_MapOfShape& theMEInverted,
+                        TopTools_MapOfShape& theEdgesInvalidByVertex);
+
+static
+  void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
+                        const TopTools_IndexedMapOfShape& theInvEdges,
+                        const TopTools_IndexedMapOfShape& theValidEdges,
+                        const TopTools_DataMapOfShapeListOfShape& theDMFLVE,
+                        const TopTools_DataMapOfShapeListOfShape& theDMFLIE,
+                        const TopTools_ListOfShape& theLENeutral,
+                        const TopTools_ListOfShape& theLEValInverted,
+                        const TopTools_MapOfShape& theMEInverted,
+                        const TopTools_MapOfShape& theEdgesInvalidByVertex,
+                        TopTools_ListOfShape& theInvFaces);
+
+static
+  gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
+                           const Standard_Integer theNbP);
+
+static
+  Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm,
+                                 const TopoDS_Face& theFOr,
+                                 const TopTools_DataMapOfShapeListOfShape& theOEImages,
+                                 const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                                 const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                                 const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
+                                 const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
+                                 const TopTools_IndexedMapOfShape& theMEdges,
+                                 TopTools_MapOfShape& theMEInverted);
+
+
+static
+  void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
+                                          TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                                          TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                                          TopTools_IndexedMapOfShape& theMERemoved);
+
+static
+  void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                                    const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                                    const TopTools_MapOfShape& theMEInverted,
+                                    TopTools_IndexedDataMapOfShapeListOfShape& theFImages);
+
+static
+  void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                         TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                         const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                         const TopTools_IndexedMapOfShape& theInvEdges,
+                         const TopTools_IndexedMapOfShape& theMFToCheckInt,
+                         TopTools_DataMapOfShapeListOfShape& theSSInterfs,
+                         TopTools_IndexedMapOfShape& theMERemoved,
+                         TopoDS_Shape& theSolids);
+
+static
+  void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                         const TopTools_IndexedMapOfShape& theInvEdges,
+                         const TopTools_DataMapOfShapeShape& theDMFOr,
+                         BOPAlgo_Builder& theBuilder,
+                         TopTools_DataMapOfShapeListOfShape& theSSInterfs);
+
+static
+  void RemoveValidSplits(const TopTools_MapOfShape& theSpRem,
+                         TopTools_IndexedDataMapOfShapeListOfShape& theImages,
+                         BOPAlgo_Builder& theGF,
+                         TopTools_IndexedMapOfShape& theMERemoved);
+
+static
+  void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem,
+                           const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                           const TopTools_IndexedMapOfShape& theInvEdges,
+                           TopTools_IndexedDataMapOfShapeListOfShape& theImages,
+                           BOPAlgo_Builder& theGF,
+                           TopTools_IndexedMapOfShape& theMERemoved);
+
+static
+  void FilterEdgesImages(const TopoDS_Shape& theS,
+                         TopTools_DataMapOfShapeListOfShape& theOEImages,
+                         TopTools_DataMapOfShapeListOfShape& theOEOrigins);
+
+static
+  void FilterInvalidFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                          const TopTools_IndexedDataMapOfShapeListOfShape& theDMFE,
+                          TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                          TopTools_DataMapOfShapeShape& theArtInvFaces);
+
+static
+  void FilterInvalidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                          const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                          const TopTools_DataMapOfShapeListOfShape& theDMFLIE,
+                          const TopTools_IndexedMapOfShape& theMERemoved,
+                          TopTools_IndexedMapOfShape& theInvEdges);
+
+static 
+  void FindFacesToRebuild(const TopTools_IndexedDataMapOfShapeListOfShape&  theLFImages,
+                          const TopTools_IndexedMapOfShape& theInvEdges,
+                          const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                          const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
+                          TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
+                          TopTools_MapOfShape& theFSelfRebAvoid);
+
+static
+  void RebuildFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
+                    const TopTools_MapOfShape& theFSelfRebAvoid,
+                    const TopoDS_Shape& theSolids,
+                    const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
+                    TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                    TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                    TopTools_DataMapOfShapeShape& theFacesOrigins,
+                    TopTools_DataMapOfShapeListOfShape& theOEImages,
+                    TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                    TopTools_MapOfShape& theLastInvEdges,
+                    TopTools_IndexedMapOfShape& theEdgesToAvoid,
+                    TopTools_IndexedMapOfShape& theInvEdges,
+                    TopTools_IndexedMapOfShape& theValidEdges,
+                    const TopTools_MapOfShape& theInvertedEdges,
+                    TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
+                    TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                    const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                    TopTools_MapOfShape& theVertsToAvoid,
+                    TopTools_DataMapOfShapeShape& theETrimEInf,
+                    Handle(BRepAlgo_AsDes)& theAsDes);
+
+static
+  void IntersectFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
+                      const TopTools_MapOfShape& theFSelfRebAvoid,
+                      const TopoDS_Shape& theSolids,
+                      const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
+                      TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                      TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                      TopTools_DataMapOfShapeListOfShape& theOEImages,
+                      TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                      TopTools_IndexedMapOfShape& theInvEdges,
+                      TopTools_IndexedMapOfShape& theValidEdges,
+                      const TopTools_MapOfShape& theInvertedEdges,
+                      TopTools_IndexedMapOfShape& theEdgesToAvoid,
+                      TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                      const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                      TopTools_MapOfShape& theVertsToAvoid,
+                      TopTools_DataMapOfShapeShape& theETrimEInf,
+                      TopTools_MapOfShape& theModifiedEdges,
+                      Handle(BRepAlgo_AsDes)& theAsDes);
+
+static
+  void PrepareFacesForIntersection(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
+                                   const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                                   const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                                   const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                                   const Standard_Boolean bLookVertToAvoid,
+                                   TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
+                                   TopTools_DataMapOfShapeListOfShape& theMDone,
+                                   TopTools_DataMapOfShapeListOfShape& theDMSF,
+                                   TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
+                                   TopTools_DataMapOfShapeListOfShape& theDMVEFull,
+                                   TopTools_DataMapOfShapeShape& theETrimEInf,
+                                   TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv);
+
+static
+  void FindVerticesToAvoid(const TopTools_IndexedDataMapOfShapeListOfShape& theDMEFInv,
+                           const TopTools_IndexedMapOfShape& theInvEdges,
+                           const TopTools_IndexedMapOfShape& theValidEdges,
+                           TopTools_DataMapOfShapeListOfShape& theDMVEFull,
+                           TopTools_MapOfShape& theMVRInv);
+
+static
+  void FindFacesForIntersection(const TopoDS_Shape& theFInv,
+                                const TopTools_IndexedMapOfShape& theME,
+                                const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                                const TopTools_DataMapOfShapeListOfShape& theDMSF,
+                                const TopTools_MapOfShape& theMVInvAll,
+                                const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                                const Standard_Boolean theArtCase,
+                                const TopTools_DataMapOfShapeListOfShape& theSSInterfs,
+                                TopTools_IndexedMapOfShape& theMFAvoid,
+                                TopTools_IndexedMapOfShape& theMFInt,
+                                TopTools_IndexedMapOfShape& theMFIntExt,
+                                TopTools_ListOfShape& theLFImInt);
+
+static
+  void ProcessCommonEdges(const TopTools_ListOfShape& theLEC,
+                          const TopTools_IndexedMapOfShape& theInvEdges,
+                          const TopTools_IndexedMapOfShape& theValidEdges,
+                          const TopTools_IndexedMapOfShape& theME,
+                          const TopTools_DataMapOfShapeShape& theETrimEInf,
+                          const TopTools_DataMapOfShapeListOfShape& theMEInfETrim,
+                          const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                          const Standard_Boolean theForceUse,
+                          TopTools_IndexedMapOfShape& theMECV,
+                          TopTools_DataMapOfShapeListOfShape& theDMEETrim,
+                          TopTools_ListOfShape& theLFEi,
+                          TopTools_ListOfShape& theLFEj,
+                          TopTools_IndexedMapOfShape& theMEToInt);
+
+static
+  void UpdateIntersectedFaces(const TopoDS_Shape& theFInv,
+                              const TopoDS_Shape& theFi,
+                              const TopoDS_Shape& theFj,
+                              const TopTools_ListOfShape& theLFInv,
+                              const TopTools_ListOfShape& theLFImi,
+                              const TopTools_ListOfShape& theLFImj,
+                              const TopTools_ListOfShape& theLFEi,
+                              const TopTools_ListOfShape& theLFEj,
+                              TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                              TopTools_IndexedMapOfShape& theMEToInt);
+
+static
+  void IntersectFaces(const TopoDS_Shape& theFInv,
+                      const TopoDS_Shape& theFi,
+                      const TopoDS_Shape& theFj,
+                      const TopTools_ListOfShape& theLFInv,
+                      const TopTools_ListOfShape& theLFImi,
+                      const TopTools_ListOfShape& theLFImj,
+                      TopTools_ListOfShape& theLFEi,
+                      TopTools_ListOfShape& theLFEj,
+                      TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                      TopTools_IndexedMapOfShape& theMECV,
+                      TopTools_IndexedMapOfShape& theMEToInt);
+
+static 
+  void FindOrigins(const TopTools_ListOfShape& theLFIm1,
+                   const TopTools_ListOfShape& theLFIm2,
+                   const TopTools_IndexedMapOfShape& theME,
+                   const TopTools_DataMapOfShapeListOfShape& theOrigins,
+                   TopTools_ListOfShape& theLEOr);
+
+static
+  void IntersectAndTrimEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
+                             const TopTools_IndexedMapOfShape& theMFInt,
+                             const TopTools_IndexedMapOfShape& theMEInt,
+                             const TopTools_DataMapOfShapeListOfShape& theDMEETrim,
+                             const TopTools_IndexedMapOfShape& theMSInv,
+                             const TopTools_IndexedMapOfShape& theMVE,
+                             const TopTools_MapOfShape& theVertsToAvoid,
+                             const TopTools_MapOfShape& theNewVertsToAvoid,
+                             TopTools_MapOfShape& theMVBounds,
+                             TopTools_DataMapOfShapeListOfShape& theEImages);
+
+static
+  void GetInvalidEdges(const TopTools_MapOfShape& theVertsToAvoid,
+                       const TopTools_MapOfShape& theMVBounds,
+                       BOPAlgo_Builder& theGF,
+                       TopTools_MapOfShape& theMEInv);
+
+static 
+  void UpdateValidEdges(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
+                        const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                        const TopTools_IndexedDataMapOfShapeListOfShape& theFLE,
+                        const TopTools_MapOfShape& theMVBounds,
+                        const TopoDS_Shape& theSolids,
+                        const TopTools_IndexedMapOfShape& theInvEdges,
+                        const TopTools_MapOfShape& theInvertedEdges,
+                        TopTools_IndexedMapOfShape& theEdgesToAvoid,
+                        TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                        TopTools_DataMapOfShapeListOfShape& theOEImages,
+                        TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                        TopTools_MapOfShape& theVertsToAvoid,
+                        TopTools_DataMapOfShapeShape& theETrimEInf,
+                        TopTools_DataMapOfShapeListOfShape& theEImages,
+                        TopTools_DataMapOfShapeListOfShape& theEETrim,
+                        TopTools_MapOfShape& theModifiedEdges,
+                        Handle(BRepAlgo_AsDes)& theAsDes);
+
+static
+  void TrimNewIntersectionEdges(const TopTools_ListOfShape& theLE,
+                                const TopTools_DataMapOfShapeListOfShape& theEETrim,
+                                const TopTools_MapOfShape& theMVBounds,
+                                TopTools_DataMapOfShapeListOfShape& theEImages,
+                                TopTools_MapOfShape& theMEB,
+                                TopTools_MapOfShape& theMVOld,
+                                TopTools_ListOfShape& theLENew,
+                                BOPCol_ListOfShape& theLA,
+                                TopTools_DataMapOfShapeListOfShape& theDMEOr);
+
+static
+  void IntersectEdges(const BOPCol_ListOfShape& theLA,
+                      const TopTools_ListOfShape& theLE,
+                      const TopTools_ListOfShape& theLENew,
+                      const TopTools_MapOfShape& theMVBounds,
+                      const TopTools_MapOfShape& theVertsToAvoid,
+                      TopTools_DataMapOfShapeListOfShape& theEImages,
+                      TopTools_MapOfShape& theModifiedEdges,
+                      TopTools_DataMapOfShapeListOfShape& theDMEOr,
+                      TopTools_MapOfShape& theMENew,
+                      TopoDS_Shape& theSplits);
+
+static
+  void GetBounds(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                 const TopTools_MapOfShape& theMEB,
+                 TopoDS_Shape& theBounds);
+
+static
+  void GetBoundsToUpdate(const TopTools_ListOfShape& theLF,
+                         const TopTools_DataMapOfShapeListOfShape& theOEImages,
+                         const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                         const TopTools_MapOfShape& theMEB,
+                         TopTools_ListOfShape& theLABounds,
+                         TopTools_ListOfShape& theLAValid,
+                         TopoDS_Shape& theBounds,
+                         Handle(BRepAlgo_AsDes)& theAsDes);
+
+static
+  void GetInvalidEdgesByBounds(const TopoDS_Shape& theSplits,
+                               const TopoDS_Shape& theBounds,
+                               const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild,
+                               const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                               const TopoDS_Shape& theSolids,
+                               const TopTools_IndexedMapOfShape& theInvEdges,
+                               const TopTools_MapOfShape& theMVOld,
+                               const TopTools_MapOfShape& theMENew,
+                               const TopTools_DataMapOfShapeListOfShape& theDMEOr,
+                               const TopTools_DataMapOfShapeListOfShape& theEImages,
+                               TopTools_MapOfShape& theVertsToAvoid,
+                               TopTools_MapOfShape& theMEInv);
+
+static
+  void UpdateNewIntersectionEdges(const TopTools_ListOfShape& theLE,
+                                  const TopTools_DataMapOfShapeListOfShape& theMELF,
+                                  const TopTools_DataMapOfShapeListOfShape& theEImages,
+                                  const TopTools_IndexedMapOfShape& theInvEdges,
+                                  const TopTools_MapOfShape& theInvertedEdges,
+                                  TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                                  TopTools_DataMapOfShapeListOfShape& theOEImages,
+                                  TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                                  TopTools_DataMapOfShapeShape& theETrimEInf,
+                                  TopTools_DataMapOfShapeListOfShape& theEETrim,
+                                  TopTools_MapOfShape& theModifiedEdges,
+                                  Handle(BRepAlgo_AsDes)& theAsDes);
+
+static
+  void FillHistory(const TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                   const TopTools_DataMapOfShapeListOfShape& theEImages,
+                   BRepAlgo_Image& theImage);
+
+static
+  void UpdateOrigins(const TopTools_ListOfShape& theLA,
+                     TopTools_DataMapOfShapeListOfShape& theOrigins,
+                     BOPAlgo_Builder& theGF);
+
+static
+  void UpdateImages(const TopTools_ListOfShape& theLA,
+                    TopTools_DataMapOfShapeListOfShape& theImages,
+                    BOPAlgo_Builder& theGF,
+                    TopTools_MapOfShape& theModified);
+
+static
+  void UpdateIntersectedEdges(const TopTools_ListOfShape& theLA,
+                              TopTools_DataMapOfShapeShape& theETrimEInf,
+                              BOPAlgo_Builder& theGF);
+
+static
+  Standard_Boolean ProcessMicroEdge(const TopoDS_Edge& theEdge,
+                                    const Handle(IntTools_Context)& theCtx);
+
+static
+  void FindCommonParts(const TopTools_ListOfShape& theLS1,
+                       const TopTools_ListOfShape& theLS2,
+                       TopTools_ListOfShape& theLSC,
+                       const TopAbs_ShapeEnum theType = TopAbs_EDGE);
+
+static
+  Standard_Integer NbPoints(const TopoDS_Edge& theE);
+
+static
+  Standard_Boolean FindShape(const TopoDS_Shape& theSWhat,
+                             const TopoDS_Shape& theSWhere,
+                             TopoDS_Shape& theRes);
+
+static
+  void AppendToList(TopTools_ListOfShape& theL,
+                    const TopoDS_Shape& theS);
+
+//=======================================================================
+//function : BuildSplitsOfTrimmedFaces
+//purpose  : Building splits of already trimmed faces
+//=======================================================================
+void BRepOffset_MakeOffset::BuildSplitsOfTrimmedFaces(const TopTools_ListOfShape& theLF,
+                                                      Handle(BRepAlgo_AsDes)& theAsDes,
+                                                      BRepAlgo_Image& theImage)
+{
+  TopTools_DataMapOfShapeListOfShape anEImages, anEOrigins;
+  TopTools_IndexedDataMapOfShapeListOfShape aDMFFIm;
+  TopTools_IndexedMapOfShape anEmptyIM;
+  TopTools_DataMapOfShapeListOfShape anEmptyDMSLS;
+  TopTools_DataMapOfShapeShape anEmptyDMSS;
+  TopTools_MapOfShape aNewEdges, anEmptyM;
+  //
+  // firstly it is necessary to fuse all the edges
+  Handle(IntTools_Context) aCtx = new IntTools_Context();
+  //
+  IntersectTrimmedEdges(theLF, theAsDes, anEImages, anEOrigins, anEmptyDMSLS, aCtx, aNewEdges, anEmptyDMSS);
+  //
+  TopTools_ListIteratorOfListOfShape aItLF(theLF);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
+    //
+    TopoDS_Shape aCE;
+    TopTools_ListOfShape aLFImages;
+    //
+    Standard_Boolean bFound = GetEdges(aF, theAsDes, anEImages, anEmptyM,
+                                       anEmptyIM, aCtx, aNewEdges, aCE, anEmptyIM);
+    // split the face by the edges
+    if (!bFound) {
+      if (!theImage.HasImage(aF)) {
+        aLFImages.Append(aF);
+        aDMFFIm.Add(aF, aLFImages);
+      }
+      continue;
+    }
+    //
+    BuildSplitsOfFace(aF, aCE, Standard_True, anEmptyDMSS, aLFImages);
+    aDMFFIm.Add(aF, aLFImages);
+  }
+  // Fill history for faces and edges
+  FillHistory(aDMFFIm, anEImages, theImage);
+}
+
+//=======================================================================
+//function : BuildSplitsOfExtendedFaces
+//purpose  : Building splits of not-trimmed offset faces.
+//           For the cases in which invalidity will be found,
+//           these invalidities will be rebuilt.
+//=======================================================================
+void BRepOffset_MakeOffset::BuildSplitsOfExtendedFaces(const TopTools_ListOfShape& theLF,
+                                                       Handle(BRepAlgo_AsDes)& theAsDes,
+                                                       TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                                                       TopTools_DataMapOfShapeShape& theFacesOrigins,
+                                                       TopTools_DataMapOfShapeShape& theETrimEInf,
+                                                       BRepAlgo_Image& theImage)
+{
+  Handle(IntTools_Context) aCtx = new IntTools_Context();
+  // images and origins for offset edges
+  TopTools_DataMapOfShapeListOfShape anOEImages, anOEOrigins;
+  TopTools_MapOfShape aNewEdges;
+  // fusing all trimmed offset edges to avoid self-intersections in the splits
+  IntersectTrimmedEdges(theLF, theAsDes, anOEImages, anOEOrigins,
+                        theEdgesOrigins, aCtx, aNewEdges, theETrimEInf);
+  //
+  // valid/invalid edges
+  TopTools_IndexedMapOfShape anInvEdges, aValidEdges, anEdgesToAvoid;
+  // inverted edges
+  TopTools_MapOfShape anInvertedEdges;
+  // splits of faces
+  TopTools_IndexedDataMapOfShapeListOfShape aFImages;
+  // found invalid faces
+  TopTools_IndexedDataMapOfShapeListOfShape anInvFaces;
+  // artificially invalid faces - it will be empty here,
+  // but may be filled on the following rebuilding steps
+  TopTools_DataMapOfShapeShape anArtInvFaces;
+  // shapes connections for using in rebuilding
+  TopTools_DataMapOfShapeListOfShape aSSInterfs;
+  // edges to avoid on second steps
+  TopTools_MapOfShape aLastInvEdges;
+  // keep information of already invalid faces to avoid
+  // infinite rebuilding of the same invalid face
+  TopTools_DataMapOfShapeInteger anAlreadyInvFaces;
+  // solid build from the new splits
+  TopoDS_Shape aSolids;
+  // now we can split the faces
+  BuildSplitsOfFaces(theLF, aNewEdges, theEdgesOrigins, theAsDes, theFacesOrigins,
+                     anOEImages, anOEOrigins, aLastInvEdges, anEdgesToAvoid, anInvEdges, aValidEdges,
+                     anInvertedEdges, anAlreadyInvFaces, anInvFaces, anArtInvFaces, aFImages, aSolids, aSSInterfs);
+  //
+  // Find faces to rebuild
+  if (anInvFaces.Extent()) {
+    TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild;
+    TopTools_MapOfShape aFSelfRebAvoid;
+    FindFacesToRebuild(aFImages, anInvEdges, anInvFaces, aSSInterfs, aFToRebuild, aFSelfRebAvoid);
+    //
+    if (aFToRebuild.Extent()) {
+      // vertices to avoid
+      TopTools_MapOfShape aVAEmpty;
+      RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aSSInterfs, aFImages, theEdgesOrigins, theFacesOrigins,
+                   anOEImages, anOEOrigins, aLastInvEdges, anEdgesToAvoid, anInvEdges, aValidEdges, anInvertedEdges,
+                   anAlreadyInvFaces, anInvFaces, anArtInvFaces, aVAEmpty, theETrimEInf, theAsDes);
+    }
+  }
+  // Fill history for faces and edges
+  FillHistory(aFImages, anOEImages, theImage);
+}
+
+//=======================================================================
+//function : BuildSplitsOfInvFaces
+//purpose  : Rebuilding splits of faces with new intersection edges
+//=======================================================================
+void BuildSplitsOfInvFaces(const TopTools_IndexedDataMapOfShapeListOfShape& theFToRebuild, 
+                           const TopTools_MapOfShape& theModifiedEdges,
+                           TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                           TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                           TopTools_DataMapOfShapeShape& theFacesOrigins,
+                           TopTools_DataMapOfShapeListOfShape& theOEImages,
+                           TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                           TopTools_MapOfShape& theLastInvEdges,
+                           TopTools_IndexedMapOfShape& theEdgesToAvoid,
+                           TopTools_MapOfShape& theVertsToAvoid,
+                           TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
+                           TopTools_IndexedMapOfShape& theValidEdges,
+                           TopTools_DataMapOfShapeShape& theETrimEInf, 
+                           Handle(BRepAlgo_AsDes)& theAsDes)
+{
+  Standard_Integer aNb = theFToRebuild.Extent();
+  if (!aNb) {
+    return;
+  }
+  //
+  TopTools_ListOfShape aLF;
+  aNb = theFImages.Extent();
+  for (Standard_Integer i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aF = theFImages.FindKey(i);
+    aLF.Append(aF);
+  }
+  //
+  // invalid faces
+  TopTools_IndexedDataMapOfShapeListOfShape anInvFaces;
+  // artificially invalid faces
+  TopTools_DataMapOfShapeShape anArtInvFaces;
+  // invalid edges
+  TopTools_IndexedMapOfShape anInvEdges;
+  // inverted edges
+  TopTools_MapOfShape anInvertedEdges;
+  // shapes connection for using in rebuilding process
+  TopTools_DataMapOfShapeListOfShape aSSInterfs;
+  //
+  TopoDS_Shape aSolids;
+  //
+  BuildSplitsOfFaces(aLF, theModifiedEdges, theEdgesOrigins, theAsDes, theFacesOrigins, 
+                     theOEImages, theOEOrigins, theLastInvEdges, theEdgesToAvoid, anInvEdges, theValidEdges, 
+                     anInvertedEdges, theAlreadyInvFaces, anInvFaces, anArtInvFaces, theFImages, aSolids, aSSInterfs);
+  //
+  if (anInvFaces.Extent()) {
+    TopTools_IndexedDataMapOfShapeListOfShape aFToRebuild;
+    TopTools_MapOfShape aFSelfRebAvoid;
+    FindFacesToRebuild(theFImages, anInvEdges, anInvFaces, aSSInterfs, aFToRebuild, aFSelfRebAvoid);
+    //
+    if (aFToRebuild.Extent()) {
+      RebuildFaces(aFToRebuild, aFSelfRebAvoid, aSolids, aSSInterfs, theFImages, theEdgesOrigins, theFacesOrigins,
+                   theOEImages, theOEOrigins, theLastInvEdges, theEdgesToAvoid, anInvEdges, theValidEdges, anInvertedEdges,
+                   theAlreadyInvFaces, anInvFaces, anArtInvFaces, theVertsToAvoid, theETrimEInf, theAsDes);
+    }
+  }
+}
+
+//=======================================================================
+//function : BuildSplitsOfFaces
+//purpose  : Building the splits of offset faces and
+//           looking for the invalid splits
+//=======================================================================
+void BuildSplitsOfFaces(const TopTools_ListOfShape& theLF,
+                        const TopTools_MapOfShape& theModifiedEdges,
+                        const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                        Handle(BRepAlgo_AsDes)& theAsDes,
+                        TopTools_DataMapOfShapeShape& theFacesOrigins,
+                        TopTools_DataMapOfShapeListOfShape& theOEImages,
+                        TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                        TopTools_MapOfShape& theLastInvEdges,
+                        TopTools_IndexedMapOfShape& theEdgesToAvoid,
+                        TopTools_IndexedMapOfShape& theInvEdges,
+                        TopTools_IndexedMapOfShape& theValidEdges,
+                        TopTools_MapOfShape& theInvertedEdges,
+                        TopTools_DataMapOfShapeInteger& theAlreadyInvFaces,
+                        TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                        TopTools_DataMapOfShapeShape& theArtInvFaces,
+                        TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                        TopoDS_Shape& theSolids,
+                        TopTools_DataMapOfShapeListOfShape& theSSInterfs)
+{
+  if (theLF.IsEmpty()) {
+    return;
+  }
+  //
+  BRep_Builder aBB;
+  Standard_Integer i, aNb;
+  //
+  // processed faces
+  TopTools_ListOfShape aLFDone;
+  // extended face - list of neutral edges, i.e. in one splits - valid and in others - invalid
+  TopTools_DataMapOfShapeListOfShape aDMFLNE;
+  // list of valid edges for each face
+  TopTools_DataMapOfShapeListOfShape aDMFLVE;
+  // list of invalid edges for each face
+  TopTools_DataMapOfShapeListOfShape aDMFLIE;
+  // map of valid inverted edges for the face
+  TopTools_DataMapOfShapeListOfShape aDMFLVIE;
+  // map of splits to check for internals
+  TopTools_IndexedMapOfShape aMFToCheckInt;
+  // map of edges created from vertex and marked as invalid
+  TopTools_MapOfShape aMEdgeInvalidByVertex;
+  //
+  Handle(IntTools_Context) aCtx = new IntTools_Context;
+  // build splits of faces
+  TopTools_ListIteratorOfListOfShape aItLF(theLF);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
+    //
+    TopTools_ListOfShape* pLFIm = theFImages.ChangeSeek(aF);
+    if (pLFIm && pLFIm->IsEmpty()) {
+      continue;
+    }
+    // get edges by which the face should be split
+    TopoDS_Shape aCE;
+    TopTools_IndexedMapOfShape aMapEInv;
+    Standard_Boolean bFound =
+      GetEdges(aF, theAsDes, theOEImages, theLastInvEdges,
+               theEdgesToAvoid, aCtx, theModifiedEdges, aCE, aMapEInv);
+    if (!bFound) {
+      continue;
+    }
+    //
+    // build splits
+    TopTools_ListOfShape aLFImages;
+    BuildSplitsOfFace(aF, aCE, Standard_False, theFacesOrigins, aLFImages);
+    //
+    if (aMapEInv.Extent()) {
+      // check if all possible faces are built
+      TopTools_MapOfShape aMENInv;
+      Standard_Boolean bArtificialCase = aLFImages.IsEmpty() ||
+        CheckIfArtificial(aF, aLFImages, aCE, aMapEInv, theOEImages, aMENInv, theAsDes);
+      //
+      // try to build splits using invalid edges
+      TopoDS_Compound aCE1;
+      aBB.MakeCompound(aCE1);
+      aBB.Add(aCE1, aCE);
+      for (i = 1; i <= aMapEInv.Extent(); ++i) {
+        aBB.Add(aCE1, aMapEInv(i));
+      }
+      //
+      TopTools_ListOfShape aLFImages1;
+      BuildSplitsOfFace(aF, aCE1, Standard_False, theFacesOrigins, aLFImages1);
+      //
+      // additionally check if newly created faces are not the same
+      Standard_Boolean bAllInv = Standard_True;
+      TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages1);
+      for (; aItLFIm.More();) {
+        const TopoDS_Shape& aFIm = aItLFIm.Value();
+        TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
+        for (; aExpE.More(); aExpE.Next()) {
+          const TopoDS_Shape& aE = aExpE.Current();
+          if (!aMapEInv.Contains(aE) && !aMENInv.Contains(aE)) {
+            break;
+          }
+          else if (bAllInv) {
+            bAllInv = aMapEInv.Contains(aE);
+          }
+        }
+        //
+        if (!aExpE.More()) {
+          if (bAllInv) {
+            aMFToCheckInt.Add(aFIm);
+          }
+          aLFImages1.Remove(aItLFIm);
+        }
+        else {
+          aItLFIm.Next();
+        }
+      }
+      //
+      if (bArtificialCase) {
+        if (aLFImages.Extent() == aLFImages1.Extent()) {
+          bArtificialCase = Standard_False;
+        }
+        else {
+          aLFImages = aLFImages1;
+        }
+      }
+      //
+      if (bArtificialCase) {
+        TopTools_ListOfShape aLEInv;
+        // make the face invalid
+        theArtInvFaces.Bind(aF, aCE);
+        //
+        *pLFIm = aLFImages;
+        TopTools_ListIteratorOfListOfShape aItLFIm(aLFImages);
+        for (; aItLFIm.More(); aItLFIm.Next()) {
+          const TopoDS_Shape& aFIm = aItLFIm.Value();
+          TopExp_Explorer aExpE(aFIm, TopAbs_EDGE);
+          for (; aExpE.More(); aExpE.Next()) {
+            const TopoDS_Shape& aE = aExpE.Current();
+            if (aMapEInv.Contains(aE)) {
+              theInvEdges.Add(aE);
+              AppendToList(aLEInv, aE);
+            }
+            else {
+              theValidEdges.Add(aE);
+            }
+          }
+        }
+        //
+        aDMFLIE.Bind(aF, aLEInv);
+        aLFDone.Append(aF);
+        //
+        continue;
+      }
+    }
+    //
+    // find invalid edges
+    FindInvalidEdges(aF, aLFImages, theEdgesOrigins, theFacesOrigins, theOEImages,
+                     theOEOrigins, theInvEdges, theValidEdges, aDMFLVE, aDMFLNE, aDMFLIE,
+                     aDMFLVIE, theInvertedEdges, aMEdgeInvalidByVertex);
+    //
+    // save the new splits
+    if (!pLFIm) {
+      pLFIm = &theFImages(theFImages.Add(aF, TopTools_ListOfShape()));
+    }
+    else {
+      pLFIm->Clear();
+    }
+    pLFIm->Append(aLFImages);
+    //
+    aLFDone.Append(aF);
+  }
+  //
+  if (theInvEdges.IsEmpty() && theArtInvFaces.IsEmpty()) {
+    return;
+  }
+  //
+#ifdef OFFSET_DEBUG
+  // show invalid edges
+  TopoDS_Compound aCEInv1;
+  BRep_Builder().MakeCompound(aCEInv1);
+  Standard_Integer aNbEInv = theInvEdges.Extent();
+  for (i = 1; i <= aNbEInv; ++i) {
+    const TopoDS_Shape& aE = theInvEdges(i);
+    BRep_Builder().Add(aCEInv1, aE);
+  }
+  //
+  TopoDS_Compound aCEVal1;
+  BRep_Builder().MakeCompound(aCEVal1);
+  aNbEInv = theValidEdges.Extent();
+  for (i = 1; i <= aNbEInv; ++i) {
+    const TopoDS_Shape& aE = theValidEdges(i);
+    BRep_Builder().Add(aCEVal1, aE);
+  }
+#endif
+  //
+  TopTools_ListOfShape anEmptyList;
+  // find invalid faces
+  // considering faces containing only invalid edges as invalid
+  aItLF.Initialize(aLFDone);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Shape& aF = aItLF.Value();
+    TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
+    //
+    TopTools_ListOfShape aLFInv;
+    Standard_Boolean bArtificialCase = theArtInvFaces.IsBound(aF);
+    if (bArtificialCase) {
+      aLFInv = aLFImages;
+    }
+    else {
+      // neutral edges
+      TopTools_ListOfShape* pLNE = aDMFLNE.ChangeSeek(aF);
+      if (!pLNE) {
+        pLNE = &anEmptyList;
+      }
+      // valid inverted edges
+      TopTools_ListOfShape* pLIVE = aDMFLVIE.ChangeSeek(aF);
+      if (!pLIVE) {
+        pLIVE = &anEmptyList;
+      }
+      //
+      FindInvalidFaces(aLFImages, theInvEdges, theValidEdges, aDMFLVE, aDMFLIE,
+                       *pLNE, *pLIVE, theInvertedEdges, aMEdgeInvalidByVertex, aLFInv);
+    }
+    //
+    if (aLFInv.Extent()) {
+      if (theAlreadyInvFaces.IsBound(aF)) {
+        if (theAlreadyInvFaces.Find(aF) > 2) {
+          if (aLFInv.Extent() == aLFImages.Extent() && !bArtificialCase) {
+            aLFImages.Clear();
+          }
+          //
+          aLFInv.Clear();
+        }
+      }
+      theInvFaces.Add(aF, aLFInv);
+    }
+  }
+  //
+  if (theInvFaces.IsEmpty()) {
+    theInvEdges.Clear();
+    return;
+  }
+  //
+#ifdef OFFSET_DEBUG
+  // show invalid faces
+  TopoDS_Compound aCFInv1;
+  BRep_Builder().MakeCompound(aCFInv1);
+  Standard_Integer aNbFInv = theInvFaces.Extent();
+  for (i = 1; i <= aNbFInv; ++i) {
+    const TopTools_ListOfShape& aLFInv = theInvFaces(i);
+    TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
+    for (; aItLFInv.More(); aItLFInv.Next()) {
+      const TopoDS_Shape& aFIm = aItLFInv.Value();
+      BRep_Builder().Add(aCFInv1, aFIm);
+    }
+  }
+#endif
+  //
+  TopTools_IndexedMapOfShape aMERemoved;
+  // remove invalid splits of faces using inverted edges
+  RemoveInvalidSplitsByInvertedEdges(theInvertedEdges, theInvFaces, theFImages, aMERemoved);
+  if (theInvFaces.IsEmpty()) {
+    theInvEdges.Clear();
+    return;
+  }
+  //
+  // remove invalid splits from valid splits
+  RemoveInvalidSplitsFromValid(theInvFaces, theArtInvFaces, theInvertedEdges, theFImages);
+  //
+  // remove inside faces
+  RemoveInsideFaces(theFImages, theInvFaces, theArtInvFaces, 
+                    theInvEdges, aMFToCheckInt, theSSInterfs, aMERemoved, theSolids);
+  //
+  // make compound of valid splits
+  TopoDS_Compound aCFIm;
+  aBB.MakeCompound(aCFIm);
+  //
+  aNb = theFImages.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopTools_ListOfShape& aLFIm = theFImages(i);
+    aItLF.Initialize(aLFIm);
+    for (; aItLF.More(); aItLF.Next()) {
+      const TopoDS_Shape& aFIm = aItLF.Value();
+      aBB.Add(aCFIm, aFIm);
+    }
+  }
+  //
+  TopTools_IndexedDataMapOfShapeListOfShape aDMFE;
+  TopExp::MapShapesAndAncestors(aCFIm, TopAbs_EDGE, TopAbs_FACE, aDMFE);
+  //
+  // filter maps of images and origins
+  FilterEdgesImages(aCFIm, theOEImages, theOEOrigins);
+  //
+  // filter invalid faces
+  FilterInvalidFaces(theFImages, aDMFE, theInvFaces, theArtInvFaces);
+  aNb = theInvFaces.Extent();
+  if (!aNb) {
+    theInvEdges.Clear();
+    return;
+  }
+  //
+#ifdef OFFSET_DEBUG
+  // show invalid faces
+  TopoDS_Compound aCFInv;
+  BRep_Builder().MakeCompound(aCFInv);
+  aNbFInv = theInvFaces.Extent();
+  for (i = 1; i <= aNbFInv; ++i) {
+    const TopTools_ListOfShape& aLFInv = theInvFaces(i);
+    TopTools_ListIteratorOfListOfShape aItLFInv(aLFInv);
+    for (; aItLFInv.More(); aItLFInv.Next()) {
+      const TopoDS_Shape& aFIm = aItLFInv.Value();
+      BRep_Builder().Add(aCFInv, aFIm);
+    }
+  }
+#endif
+  //
+  // filter invalid edges
+  FilterInvalidEdges(theInvFaces, theArtInvFaces, aDMFLIE, aMERemoved, theInvEdges);
+  //
+#ifdef OFFSET_DEBUG
+  // show invalid edges
+  TopoDS_Compound aCEInv;
+  BRep_Builder().MakeCompound(aCEInv);
+  aNbEInv = theInvEdges.Extent();
+  for (i = 1; i <= aNbEInv; ++i) {
+    const TopoDS_Shape& aE = theInvEdges(i);
+    BRep_Builder().Add(aCEInv, aE);
+  }
+#endif
+  //
+  theLastInvEdges.Clear();
+  aNb = theInvEdges.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aE = theInvEdges(i);
+    theEdgesToAvoid.Add(aE);
+    theLastInvEdges.Add(aE);
+  }
+  //
+  aNb = theInvFaces.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aF = theInvFaces.FindKey(i);
+    if (theAlreadyInvFaces.IsBound(aF)) {
+      theAlreadyInvFaces.ChangeFind(aF)++;
+    }
+    else {
+      theAlreadyInvFaces.Bind(aF, 1);
+    }
+  }
+}
+
+//=======================================================================
+//function : IntersectTrimmedEdges
+//purpose  : Intersection of the trimmed edges among themselves
+//=======================================================================
+void IntersectTrimmedEdges(const TopTools_ListOfShape& theLF,
+                           const Handle(BRepAlgo_AsDes)& theAsDes,
+                           TopTools_DataMapOfShapeListOfShape& theOEImages,
+                           TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                           TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                           Handle(IntTools_Context)& theCtx,
+                           TopTools_MapOfShape& theNewEdges,
+                           TopTools_DataMapOfShapeShape& theETrimEInf)
+{
+  if (theLF.IsEmpty()) {
+    return;
+  }
+  //
+  // get edges to intersect from descendants of the offset faces
+  BOPCol_ListOfShape aLS;
+  //
+  TopTools_ListIteratorOfListOfShape aItLF(theLF);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Face& aF = *(TopoDS_Face*)&aItLF.Value();
+    //
+    const TopTools_ListOfShape& aLE = theAsDes->Descendant(aF);
+    TopTools_ListIteratorOfListOfShape aItLE(aLE);
+    for (; aItLE.More(); aItLE.Next()) {
+      const TopoDS_Edge& aE = *(TopoDS_Edge*)&aItLE.Value();
+      //
+      if (ProcessMicroEdge(aE, theCtx)) {
+        continue;
+      }
+      //
+      if (theNewEdges.Add(aE)) {
+        aLS.Append(aE);
+      }
+    }
+  }
+  //
+  if (aLS.Extent() < 2) {
+    // nothing to intersect
+    return;
+  }
+  //
+  // perform intersection of the edges
+  BOPAlgo_Builder aGFE;
+  aGFE.SetArguments(aLS);
+  aGFE.Perform();
+  if (aGFE.ErrorStatus()) {
+    return;
+  }
+  //
+  TopTools_ListOfShape aLA;
+  // fill map with edges images
+  BOPCol_ListIteratorOfListOfShape aIt(aLS);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aE = aIt.Value();
+    const TopTools_ListOfShape& aLEIm = aGFE.Modified(aE);
+    if (aLEIm.IsEmpty()) {
+      continue;
+    }
+    //
+    aLA.Append(aE);
+    // save images
+    theOEImages.Bind(aE, aLEIm);
+    // save origins
+    TopTools_ListIteratorOfListOfShape aItLE(aLEIm);
+    for (; aItLE.More(); aItLE.Next()) {
+      const TopoDS_Shape& aEIm = aItLE.Value();
+      TopTools_ListOfShape* pLEOr = theOEOrigins.ChangeSeek(aEIm);
+      if (!pLEOr) {
+        pLEOr = theOEOrigins.Bound(aEIm, TopTools_ListOfShape());
+      }
+      AppendToList(*pLEOr, aE);
+    }
+  }
+  //
+  UpdateOrigins(aLA, theEdgesOrigins, aGFE);
+  UpdateIntersectedEdges(aLA, theETrimEInf, aGFE);
+}
+
+//=======================================================================
+//function : GetEdges
+//purpose  : Getting edges from AsDes map to build the splits of faces
+//=======================================================================
+Standard_Boolean GetEdges(const TopoDS_Face& theFace,
+                          const Handle(BRepAlgo_AsDes)& theAsDes,
+                          const TopTools_DataMapOfShapeListOfShape& theEImages,
+                          const TopTools_MapOfShape& theLastInvEdges,
+                          const TopTools_IndexedMapOfShape& theInvEdges,
+                          Handle(IntTools_Context)& theCtx,
+                          const TopTools_MapOfShape& theModifiedEdges,
+                          TopoDS_Shape& theEdges,
+                          TopTools_IndexedMapOfShape& theInv)
+{
+  // get boundary edges
+  TopTools_MapOfShape aMFBounds;
+  TopExp_Explorer aExp(theFace, TopAbs_EDGE);
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Shape& aE = aExp.Current();
+    const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE);
+    if (!pLEIm) {
+      aMFBounds.Add(aE);
+    }
+    else {
+      TopTools_ListIteratorOfListOfShape aItLE(*pLEIm);
+      for (; aItLE.More(); aItLE.Next()) {
+        const TopoDS_Shape& aEIm = aItLE.Value();
+        aMFBounds.Add(aEIm);
+      }
+    }
+  }
+  //
+  BRep_Builder aBB;
+  Standard_Boolean bFound(Standard_False), bUpdate(Standard_False);
+  // the resulting edges
+  TopoDS_Compound anEdges;
+  aBB.MakeCompound(anEdges);
+  //
+  // the edges by which the offset face should be split
+  const TopTools_ListOfShape& aLE = theAsDes->Descendant(theFace);
+  TopTools_ListIteratorOfListOfShape aItLE(aLE);
+  for (; aItLE.More(); aItLE.Next()) {
+    const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
+    //
+    if (!bUpdate) {
+      bUpdate = theModifiedEdges.Contains(aE);
+    }
+    //
+    const TopTools_ListOfShape* pLEIm = theEImages.Seek(aE);
+    if (pLEIm) {
+      TopTools_ListIteratorOfListOfShape aItLEIm(*pLEIm);
+      for (; aItLEIm.More(); aItLEIm.Next()) {
+        const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value());
+        //
+        if (theInvEdges.Contains(aEIm)) {
+          theInv.Add(aEIm);
+          if (!bUpdate) {
+            bUpdate = theLastInvEdges.Contains(aEIm);
+          }
+          continue;
+        }
+        // check for micro edge
+        if (ProcessMicroEdge(aEIm, theCtx)) {
+          continue;
+        }
+        //
+        aBB.Add(anEdges, aEIm);
+        if (!bFound) {
+          bFound = !aMFBounds.Contains(aEIm);
+        }
+        //
+        if (!bUpdate) {
+          bUpdate = theModifiedEdges.Contains(aEIm);
+        }
+      }
+    }
+    else {
+      if (theInvEdges.Contains(aE)) {
+        theInv.Add(aE);
+        if (!bUpdate) {
+          bUpdate = theLastInvEdges.Contains(aE);
+        }
+        continue;
+      }
+      //
+      if (ProcessMicroEdge(aE, theCtx)) {
+        continue;
+      }
+      aBB.Add(anEdges, aE);
+      if (!bFound) {
+        bFound = !aMFBounds.Contains(aE);
+      }
+    }
+  }
+  //
+  theEdges = anEdges;
+  return bFound && bUpdate;
+}
+
+//=======================================================================
+//function : BuildSplitsOfFace
+//purpose  : Building the splits of offset face
+//=======================================================================
+void BuildSplitsOfFace(const TopoDS_Face& theFace,
+                       const TopoDS_Shape& theEdges,
+                       Standard_Boolean bTrimmed,
+                       TopTools_DataMapOfShapeShape& theFacesOrigins,
+                       TopTools_ListOfShape& theLFImages)
+{
+  BOPAlgo_Builder aGF;
+  //
+  aGF.AddArgument(theFace);
+  aGF.AddArgument(theEdges);
+  aGF.Perform();
+  if (aGF.ErrorStatus()) {
+    return;
+  }
+  //
+  // splits of the offset shape
+  theLFImages = aGF.Modified(theFace);
+  if (theLFImages.IsEmpty()) {
+    return;
+  }
+  //
+  if (!bTrimmed) {
+    // get the real splits of faces by removing the faces
+    // containing boundaries of the extended faces
+
+    // get edges to map
+    TopTools_IndexedMapOfShape aME;
+    TopExp::MapShapes(theEdges, TopAbs_EDGE, aME);
+    //
+    TopTools_ListIteratorOfListOfShape aItLE(theLFImages);
+    for (; aItLE.More();) {
+      const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLE.Value();
+      //
+      TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
+      for (; aExp.More(); aExp.Next()) {
+        const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
+        if (!aME.Contains(aE)) {
+          break;
+        }
+      }
+      //
+      if (!aExp.More()) {
+        aItLE.Next();
+      }
+      else {
+        theLFImages.Remove(aItLE);
+      }
+    }
+  }
+  // update origins
+  TopTools_ListIteratorOfListOfShape aIt(theLFImages);
+  for (; aIt.More(); aIt.Next()) {
+    const TopoDS_Shape& aFIm = aIt.Value();
+    theFacesOrigins.Bind(aFIm, theFace);
+  }
+}
+
+//=======================================================================
+//function : CheckIfArtificial
+//purpose  : Checks if the face is artificially invalid
+//=======================================================================
+Standard_Boolean CheckIfArtificial(const TopoDS_Shape& theF,
+                                   const TopTools_ListOfShape& theLFImages,
+                                   const TopoDS_Shape& theCE,
+                                   const TopTools_IndexedMapOfShape& theMapEInv,
+                                   const TopTools_DataMapOfShapeListOfShape& theOEImages,
+                                   TopTools_MapOfShape& theMENInv,
+                                   Handle(BRepAlgo_AsDes)& theAsDes)
+{
+  // all boundary edges should be used
+  TopTools_IndexedMapOfShape aMEUsed;
+  TopTools_ListIteratorOfListOfShape aItLFIm(theLFImages);
+  for (; aItLFIm.More(); aItLFIm.Next()) {
+    const TopoDS_Shape& aFIm = aItLFIm.Value();
+    TopExp::MapShapes(aFIm, TopAbs_EDGE, aMEUsed);
+    TopExp::MapShapes(aFIm, TopAbs_VERTEX, aMEUsed);
+  }
+  //
+  TopTools_IndexedDataMapOfShapeListOfShape aMVE;
+  TopExp::MapShapesAndAncestors(theCE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
+  //
+  Standard_Integer i, aNb = theMapEInv.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aEInv = theMapEInv(i);
+    TopExp_Explorer aExpV(aEInv, TopAbs_VERTEX);
+    for (; aExpV.More(); aExpV.Next()) {
+      const TopoDS_Shape& aVEInv = aExpV.Current();
+      if (!aMEUsed.Contains(aVEInv) && aMVE.Contains(aVEInv)) {
+        const TopTools_ListOfShape& aLENInv = aMVE.FindFromKey(aVEInv);
+        TopTools_ListIteratorOfListOfShape aItLEInv(aLENInv);
+        for (; aItLEInv.More(); aItLEInv.Next()) {
+          const TopoDS_Shape& aENInv = aItLEInv.Value();
+          theMENInv.Add(aENInv);
+        }
+      }
+    }
+  }
+  //
+  if (theMENInv.IsEmpty()) {
+    return Standard_False;
+  }
+  //
+  TopTools_IndexedMapOfShape aMEFound;
+  TopExp::MapShapes(theCE, TopAbs_EDGE, aMEFound);
+  //
+  const TopTools_ListOfShape& aLE = theAsDes->Descendant(theF);
+  TopTools_ListIteratorOfListOfShape aItLE(aLE);
+  for (; aItLE.More(); aItLE.Next()) {
+    const TopoDS_Edge& aE = TopoDS::Edge(aItLE.Value());
+    //
+    if (theOEImages.IsBound(aE)) {
+      Standard_Boolean bChecked = Standard_False;
+      const TopTools_ListOfShape& aLEIm = theOEImages.Find(aE);
+      TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
+      for (; aItLEIm.More(); aItLEIm.Next()) {
+        const TopoDS_Edge& aEIm = TopoDS::Edge(aItLEIm.Value());
+        if (!aMEFound.Contains(aEIm) || theMENInv.Contains(aEIm)) {
+          continue;
+        }
+        //
+        bChecked = Standard_True;
+        if (aMEUsed.Contains(aEIm)) {
+          break;
+        }
+      }
+      //
+      if (bChecked && !aItLEIm.More()) {
+        break;
+      }
+    }
+    else {
+      if (aMEFound.Contains(aE) && !theMENInv.Contains(aE) && !aMEUsed.Contains(aE)) {
+        break;
+      }
+    }
+  }
+  //
+  return aItLE.More();
+}
+
+//=======================================================================
+//function : FindInvalidEdges
+//purpose  : Looking for the invalid edges
+//=======================================================================
+void FindInvalidEdges(const TopoDS_Face& theF,
+                      const TopTools_ListOfShape& theLFImages,
+                      const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                      const TopTools_DataMapOfShapeShape& theFacesOrigins,
+                      const TopTools_DataMapOfShapeListOfShape& theOEImages,
+                      const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                      TopTools_IndexedMapOfShape& theInvEdges,
+                      TopTools_IndexedMapOfShape& theValidEdges,
+                      TopTools_DataMapOfShapeListOfShape& theDMFLVE,
+                      TopTools_DataMapOfShapeListOfShape& theDMFLNE,
+                      TopTools_DataMapOfShapeListOfShape& theDMFLIE,
+                      TopTools_DataMapOfShapeListOfShape& theDMFLVIE,
+                      TopTools_MapOfShape& theMEInverted,
+                      TopTools_MapOfShape& theEdgesInvalidByVertex)
+{
+  // Edge is considered as invalid in the following cases:
+  // 1. Its orientation on the face has changed comparing to the originals edge and face;
+  // 2. The vertices of the edge have changed places comparing to the originals edge and face.
+  //
+  // The edges created from vertices, i.e. as intersection between two faces connected only
+  // by VERTEX, will also be checked on validity. For these edges the correct orientation will
+  // be defined by the edges on the original face adjacent to the connection vertex
+  //
+  const TopoDS_Face& aFOr = *(TopoDS_Face*)&theFacesOrigins.Find(theF);
+  // invald edges
+  TopTools_IndexedMapOfShape aMEInv;
+  // valid edges
+  TopTools_MapOfShape aMEVal;
+  // internal edges
+  TopTools_MapOfShape aMEInt;
+  //
+  // maps for checking the inverted edges
+  TopTools_IndexedDataMapOfShapeListOfShape aDMVE, aDMEF;
+  TopTools_IndexedMapOfShape aMEdges;
+  //
+  TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+    //
+    TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
+    for (; aExp.More(); aExp.Next()) {
+      const TopoDS_Shape& aE = aExp.Current();
+      // keep all edges
+      aMEdges.Add(aE);
+      //
+      // keep connection from edges to faces
+      TopTools_ListOfShape* pLF = aDMEF.ChangeSeek(aE);
+      if (!pLF) {
+        pLF = &aDMEF(aDMEF.Add(aE, TopTools_ListOfShape()));
+      }
+      AppendToList(*pLF, aFIm);
+      //
+      // keep connection from vertices to edges
+      TopoDS_Iterator aItV(aE);
+      for (; aItV.More(); aItV.Next()) {
+        const TopoDS_Shape& aV = aItV.Value();
+        //
+        TopTools_ListOfShape* pLE = aDMVE.ChangeSeek(aV);
+        if (!pLE) {
+          pLE = &aDMVE(aDMVE.Add(aV, TopTools_ListOfShape()));
+        }
+        AppendToList(*pLE, aE);
+      }
+    }
+  }
+  //
+  // the map will be used to find the edges on the original face
+  // adjacent to the same vertex. It will be filled at first necessity;
+  TopTools_IndexedDataMapOfShapeListOfShape aDMVEFOr;
+  //
+  aItLF.Initialize(theLFImages);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+    //
+    // valid edges for this split
+    TopTools_ListOfShape aLVE;
+    // invalid edges for this split
+    TopTools_ListOfShape aLIE;
+    //
+    TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
+    for (; aExp.More(); aExp.Next()) {
+      const TopoDS_Edge& aEIm = *(TopoDS_Edge*)&aExp.Current();
+      //
+      if (aEIm.Orientation() == TopAbs_INTERNAL) {
+        aMEInt.Add(aEIm);
+        continue;
+      }
+      //
+      if (!theEdgesOrigins.IsBound(aEIm)) {
+        continue;
+      }
+      //
+      const TopTools_ListOfShape& aLEOr = theEdgesOrigins.Find(aEIm);
+      if (aLEOr.IsEmpty()) {
+        continue;
+      }
+      //
+      Standard_Integer aNbVOr = 0;
+      TopTools_ListIteratorOfListOfShape aItLEO(aLEOr);
+      for (; aItLEO.More(); aItLEO.Next()) {
+        if (aItLEO.Value().ShapeType() == TopAbs_VERTEX) {
+          ++aNbVOr;
+        }
+      }
+      //
+      TopTools_MapOfShape aME, aMV;
+      Standard_Boolean bInvalid = Standard_False, bChecked = Standard_False;
+      Standard_Integer aNbP = NbPoints(aEIm);
+      aItLEO.Initialize(aLEOr);
+      for (; aItLEO.More(); aItLEO.Next()) {
+        const TopoDS_Shape& aSOr = aItLEO.Value();
+        Standard_Boolean bVertex = (aSOr.ShapeType() == TopAbs_VERTEX);
+        //
+        TopoDS_Shape aEOrF;
+        if (bVertex) {
+          // for some cases it is impossible to check the validity of the edge
+          if (aNbVOr > 1) {
+            continue;
+          }
+          //
+          if (aDMEF.FindFromKey(aEIm).Extent() > 1) {
+            continue;
+          }
+          //
+          if (theOEOrigins.IsBound(aEIm)) {
+            continue;
+          }
+          //
+          // find edges on the original face adjacent to this vertex
+          if (aDMVEFOr.IsEmpty()) {
+            // fill the map
+            TopExp::MapShapesAndAncestors(aFOr, TopAbs_VERTEX, TopAbs_EDGE, aDMVEFOr);
+          }
+          //
+          TopTools_ListOfShape *pLEFOr = aDMVEFOr.ChangeSeek(aSOr);
+          if (pLEFOr) {
+            TopoDS_Compound aCEOr;
+            BRep_Builder().MakeCompound(aCEOr);
+            TopTools_ListIteratorOfListOfShape aItLEFOr(*pLEFOr);
+            for (; aItLEFOr.More(); aItLEFOr.Next()) {
+              const TopoDS_Shape& aEOr = aItLEFOr.Value();
+              BRep_Builder().Add(aCEOr, aEOr);
+            }
+            aEOrF = aCEOr;
+          }
+        }
+        else {
+          FindShape(aSOr, aFOr, aEOrF);
+        }
+        //
+        if (aEOrF.IsNull()) {
+          // the edge has not been found
+          continue;
+        }
+        //
+        // Check orientations of the image edge and original edge.
+        // In case the 3d curves are having the same direction the orientations 
+        // must be the same. Otherwise the orientations should also be different.
+        //
+        // get average tangent vector for each curve taking into account
+        // the orientations of the edges, i.e. the edge is reversed
+        // the vector is reversed as well
+        gp_Vec aVSum1 = GetAverageTangent(aEIm, aNbP);
+        gp_Vec aVSum2 = GetAverageTangent(aEOrF, aNbP);
+        //
+        aVSum1.Normalize();
+        aVSum2.Normalize();
+        //
+        Standard_Real aCos = aVSum1.Dot(aVSum2);
+        if (!bVertex) {
+          if (Abs(aCos) < 0.9999) {
+            continue;
+          }
+          //
+          aME.Add(aEOrF);
+          TopExp_Explorer aExpE(aEOrF, TopAbs_VERTEX);
+          for (; aExpE.More(); aExpE.Next()) {
+            const TopoDS_Shape& aV = aExpE.Current();
+            aMV.Add(aV);
+          }
+        }
+        //
+        if (aCos < Precision::Confusion()) {
+          bInvalid = Standard_True;
+          if (bVertex) {
+            theEdgesInvalidByVertex.Add(aEIm);
+          }
+        }
+        bChecked = Standard_True;
+      }
+      //
+      if (!bChecked) {
+        continue;
+      }
+      //
+      Standard_Integer aNbE = aME.Extent(), aNbV = aMV.Extent();
+      if ((aNbE > 1) && (aNbV == 2*aNbE)) {
+        continue;
+      }
+      //
+      if (bInvalid) {
+        theInvEdges.Add(aEIm);
+        aLIE.Append(aEIm);
+        aMEInv.Add(aEIm);
+        continue;
+      }
+      //
+      // check if the edge has been inverted
+      Standard_Boolean bInverted = CheckInverted(aEIm, aFOr, theOEImages, theOEOrigins,
+        theEdgesOrigins, aDMEF, aDMVE, aMEdges, theMEInverted);
+      //
+      if (!bInverted || !aNbVOr) {
+        theValidEdges.Add(aEIm);
+        aLVE.Append(aEIm);
+        aMEVal.Add(aEIm);
+      }
+    }
+    //
+    // valid edges
+    if (aLVE.Extent()) {
+      theDMFLVE.Bind(aFIm, aLVE);
+    }
+    //
+    // invalid edges
+    if (aLIE.Extent()) {
+      theDMFLIE.Bind(aFIm, aLIE);
+    }
+  }
+  //
+  // process invalid edges:
+  // check for the inverted edges
+  TopTools_ListOfShape aLVIE;
+  // fill neutral edges
+  TopTools_ListOfShape aLNE;
+  //
+  Standard_Integer i, aNbEInv = aMEInv.Extent();
+  for (i = 1; i <= aNbEInv; ++i) {
+    const TopoDS_Shape& aEIm = aMEInv(i);
+    //
+    // neutral edges - on the splits of the same offset face
+    // it is valid for one split and invalid for other
+    if (aMEVal.Contains(aEIm)) {
+      aLNE.Append(aEIm);
+      continue;
+    }
+    //
+    // the inverted images of the origins of invalid edges should also be invalid
+    if (!theMEInverted.Contains(aEIm)) {
+      continue;
+    }
+    //
+    const TopTools_ListOfShape* pLOEOr = theOEOrigins.Seek(aEIm);
+    if (!pLOEOr) {
+      continue;
+    }
+    //
+    TopTools_ListIteratorOfListOfShape aItLOEOr(*pLOEOr);
+    for (; aItLOEOr.More(); aItLOEOr.Next()) {
+      const TopoDS_Shape& aOEOr = aItLOEOr.Value();
+      const TopTools_ListOfShape& aLEIm1 = theOEImages.Find(aOEOr);
+      //
+      TopTools_ListIteratorOfListOfShape aItLEIm1(aLEIm1);
+      for (; aItLEIm1.More(); aItLEIm1.Next()) {
+        const TopoDS_Shape& aEIm1 = aItLEIm1.Value();
+        if (aMEdges.Contains(aEIm1) &&
+            !aMEInv.Contains(aEIm1) && !aMEInt.Contains(aEIm1) &&
+            theMEInverted.Contains(aEIm1)) {
+          theInvEdges.Add(aEIm1);
+          aLVIE.Append(aEIm1);
+        }
+      }
+    }
+  }
+  //
+  if (aLNE.Extent()) {
+    theDMFLNE.Bind(theF, aLNE);
+  }
+  //
+  if (aLVIE.Extent()) {
+    theDMFLVIE.Bind(theF, aLVIE);
+  }
+}
+
+//=======================================================================
+//function : FindInvalidFaces
+//purpose  : Looking for the invalid faces by analyzing their invalid edges
+//=======================================================================
+void FindInvalidFaces(TopTools_ListOfShape& theLFImages,
+                      const TopTools_IndexedMapOfShape& theInvEdges,
+                      const TopTools_IndexedMapOfShape& theValidEdges,
+                      const TopTools_DataMapOfShapeListOfShape& theDMFLVE,
+                      const TopTools_DataMapOfShapeListOfShape& theDMFLIE,
+                      const TopTools_ListOfShape& theLENeutral,
+                      const TopTools_ListOfShape& theLEValInverted,
+                      const TopTools_MapOfShape& theMEInverted,
+                      const TopTools_MapOfShape& theEdgesInvalidByVertex,
+                      TopTools_ListOfShape& theInvFaces)
+{
+  // The face should be considered as invalid in the following cases:
+  // 1. It has been reverted, i.e. at least two not connected edges 
+  //    have changed orientation (i.e. invalid). In this case all edges,
+  //    should be invalid for that face, because edges have also been reverted;
+  // 2. All checked edges of the face are invalid for this face;
+  // The face should be removed from the splits in the following cases:
+  // 1. All checked edges of the face are invalid for this one, but valid for
+  //    some other face in this list of splits.
+  // The face will be kept in the following cases:
+  // 1. Some of the edges are valid for this face.
+  Standard_Boolean bHasValid, bAllValid, bAllInvalid, bHasReallyInvalid, bAllInvNeutral;
+  Standard_Boolean bValid, bValidLoc, bInvalid, bInvalidLoc, bNeutral;
+  Standard_Integer i, aNbChecked;
+  //
+  // neutral edges
+  TopTools_MapOfShape aMEN;
+  TopTools_ListIteratorOfListOfShape aItLE(theLENeutral);
+  for (; aItLE.More(); aItLE.Next()) {
+    aMEN.Add(aItLE.Value());
+  }
+  //
+  // valid inverted edges
+  TopTools_MapOfShape aMEValInverted;
+  aItLE.Initialize(theLEValInverted);
+  for (; aItLE.More(); aItLE.Next()) {
+    aMEValInverted.Add(aItLE.Value());
+  }
+  //
+  Standard_Boolean bCheckInverted = (theLFImages.Extent() == 1);
+  //
+  // neutral edges to remove
+  TopTools_IndexedMapOfShape aMENRem;
+  //
+  // faces for post treat
+  TopTools_ListOfShape aLFPT;
+  //
+  TopTools_ListIteratorOfListOfShape aItLF(theLFImages);
+  for (; aItLF.More(); ) {
+    const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+    //
+    // valid edges for this split
+    TopTools_MapOfShape aMVE;
+    // invalid edges for this split
+    TopTools_MapOfShape aMIE;
+    //
+    for (i = 0; i < 2; ++i) {
+      TopTools_MapOfShape& aME = !i ? aMVE : aMIE;
+      const TopTools_ListOfShape* pLE = !i ? theDMFLVE.Seek(aFIm) : theDMFLIE.Seek(aFIm);
+      if (pLE) {
+        TopTools_ListIteratorOfListOfShape aItLE(*pLE);
+        for (; aItLE.More(); aItLE.Next()) {
+          const TopoDS_Shape& aE = aItLE.Value();
+          aME.Add(aE);
+        }
+      }
+    }
+    //
+    bHasValid = Standard_False;
+    bAllValid = Standard_True;
+    bAllInvalid = Standard_True;
+    bHasReallyInvalid = Standard_False;
+    bAllInvNeutral = Standard_True;
+    aNbChecked = 0;
+    //
+    const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
+    TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
+    for (; aExp.More(); aExp.Next()) {
+      const TopoDS_Shape& aEIm = aExp.Current();
+      //
+      bValid = theValidEdges.Contains(aEIm);
+      bInvalid = theInvEdges.Contains(aEIm);
+      //
+      if (!bValid && !bInvalid) {
+        // edge has not been checked for some reason
+        continue;
+      }
+      //
+      ++aNbChecked;
+      //
+      bInvalidLoc = aMIE.Contains(aEIm);
+      bHasReallyInvalid = bInvalidLoc && !bValid && !theEdgesInvalidByVertex.Contains(aEIm);
+      if (bHasReallyInvalid) {
+        break;
+      }
+      //
+      bNeutral = aMEN.Contains(aEIm);
+      bValidLoc = aMVE.Contains(aEIm);
+      //
+      if (!bInvalid && bCheckInverted) {
+        bInvalid = theMEInverted.Contains(aEIm);
+      }
+      //
+      if (bValidLoc && (bNeutral || aMEValInverted.Contains(aEIm))) {
+        bHasValid = Standard_True;
+      }
+      //
+      bAllValid = bAllValid && bValidLoc;
+      bAllInvalid = bAllInvalid && bInvalid;
+      bAllInvNeutral = bAllInvNeutral && bAllInvalid && bNeutral;
+    }
+    //
+    if (!aNbChecked) {
+      aItLF.Next();
+      continue;
+    }
+    //
+    if (!bHasReallyInvalid && (bAllInvNeutral && !bHasValid) && (aNbChecked > 1)) {
+      // remove edges from neutral
+      TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
+      // remove face
+      theLFImages.Remove(aItLF);
+      continue;
+    }
+    //
+    if (bHasReallyInvalid || (bAllInvalid && 
+                             !(bHasValid || bAllValid) &&
+                             !(bAllInvNeutral && (aNbChecked == 1)))) {
+      theInvFaces.Append(aFIm);
+    }
+    //
+    if (!bAllInvNeutral) {
+      aLFPT.Append(aFIm);
+    }
+    else {
+      // remove edges from neutral
+      TopExp::MapShapes(aFIm, TopAbs_EDGE, aMENRem);
+    }
+    aItLF.Next();
+  }
+  //
+  if (aLFPT.IsEmpty() || aMENRem.IsEmpty()) {
+    return;
+  }
+  //
+  Standard_Integer aNb = aMENRem.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    aMEN.Remove(aMENRem(i));
+  }
+  //
+  // check the splits once more
+  aItLF.Initialize(aLFPT);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Face& aFIm = *(TopoDS_Face*)&aItLF.Value();
+    //
+    // valid edges for this split
+    TopTools_MapOfShape aMVE;
+    const TopTools_ListOfShape* pLVE = theDMFLVE.Seek(aFIm);
+    if (pLVE) {
+      TopTools_ListIteratorOfListOfShape aItLE(*pLVE);
+      for (; aItLE.More(); aItLE.Next()) {
+        const TopoDS_Shape& aE = aItLE.Value();
+        aMVE.Add(aE);
+      }
+    }
+    //
+    bHasValid = Standard_False;
+    bAllValid = Standard_True;
+    bAllInvalid = Standard_True;
+    //
+    const TopoDS_Wire& aWIm = BRepTools::OuterWire(aFIm);
+    TopExp_Explorer aExp(aWIm, TopAbs_EDGE);
+    for (; aExp.More(); aExp.Next()) {
+      const TopoDS_Shape& aEIm = aExp.Current();
+      //
+      bValid = theValidEdges.Contains(aEIm);
+      bInvalid = theInvEdges.Contains(aEIm);
+      bNeutral = aMEN.Contains(aEIm);
+      bValidLoc = aMVE.Contains(aEIm);
+      //
+      if (!bInvalid && bCheckInverted) {
+        bInvalid = theMEInverted.Contains(aEIm);
+      }
+      //
+      if (bValidLoc && (bNeutral || aMEValInverted.Contains(aEIm))) {
+        bHasValid = Standard_True;
+      }
+      //
+      bAllValid = bAllValid && bValidLoc;
+      bAllInvalid = bAllInvalid && bInvalid;
+    }
+    //
+    if (bAllInvalid && !bHasValid && !bAllValid) {
+      theInvFaces.Append(aFIm);
+    }
+  }
+}
+
+//=======================================================================
+//function : GetAverageTangent
+//purpose  : Computes average tangent vector along the curve
+//=======================================================================
+gp_Vec GetAverageTangent(const TopoDS_Shape& theS,
+                         const Standard_Integer theNbP)
+{
+  gp_Vec aVA;
+  TopExp_Explorer aExp(theS, TopAbs_EDGE);
+  for (; aExp.More(); aExp.Next()) {
+    const TopoDS_Edge& aE = *(TopoDS_Edge*)&aExp.Current();
+    //
+    Standard_Real aT1, aT2;
+    const Handle(Geom_Curve)& aC = BRep_Tool::Curve(aE, aT1, aT2);
+    //
+    gp_Pnt aP;
+    gp_Vec aV, aVSum;
+    Standard_Real aT = aT1;
+    Standard_Real aDt = (aT2 - aT1) / theNbP;
+    while (aT <= aT2) {
+      aC->D1(aT, aP, aV);
+      aVSum += aV.Normalized();
+      aT += aDt;
+    }
+    //
+    if (aE.Orientation() == TopAbs_REVERSED) {
+      aVSum.Reverse();
+    }
+    //
+    aVA += aVSum;
+  }
+  return aVA;
+}
+
+//=======================================================================
+//function : CheckInverted
+//purpose  : Checks if the edge has been inverted
+//=======================================================================
+Standard_Boolean CheckInverted(const TopoDS_Edge& theEIm,
+                               const TopoDS_Face& theFOr,
+                               const TopTools_DataMapOfShapeListOfShape& theOEImages,
+                               const TopTools_DataMapOfShapeListOfShape& theOEOrigins,
+                               const TopTools_DataMapOfShapeListOfShape& theEdgesOrigins,
+                               const TopTools_IndexedDataMapOfShapeListOfShape& theDMEF,
+                               const TopTools_IndexedDataMapOfShapeListOfShape& theDMVE,
+                               const TopTools_IndexedMapOfShape& theMEdges,
+                               TopTools_MapOfShape& theMEInverted)
+{
+  if (theDMEF.FindFromKey(theEIm).Extent() > 1) {
+    return Standard_False;
+  }
+  //
+  if (theMEInverted.Contains(theEIm)) {
+    return Standard_True;
+  }
+  //
+  // it is necessary to compare the direction from first vertex
+  // to the last vertex on the original edge with the
+  // same direction on the new edge. If the directions
+  // will be different - the edge has been inverted.
+  //
+  TopoDS_Vertex aVI1, aVI2; // vertices on the offset edge
+  TopoDS_Vertex aVO1, aVO2; // vertices on the original edge
+  //
+  Standard_Integer i;
+  // find vertices of the offset shape
+  TopExp::Vertices(theEIm, aVI1, aVI2);
+  //
+  // find images
+  TopTools_ListOfShape aLEImages;
+  if (theOEOrigins.IsBound(theEIm)) {
+    TopoDS_Wire anImages;
+    BRep_Builder().MakeWire(anImages);
+    //
+    TopTools_MapOfShape aMImFence;
+    const TopTools_ListOfShape& aLOffsetOr = theOEOrigins.Find(theEIm);
+    TopTools_ListIteratorOfListOfShape aItOffset(aLOffsetOr);
+    for (; aItOffset.More(); aItOffset.Next()) {
+      const TopoDS_Shape& aEOffsetOr = aItOffset.Value();
+      const TopTools_ListOfShape& aLImages = theOEImages.Find(aEOffsetOr);
+      //
+      TopTools_ListIteratorOfListOfShape aItImages(aLImages);
+      for (; aItImages.More(); aItImages.Next()) {
+        const TopoDS_Edge& anIm = *(TopoDS_Edge*)&aItImages.Value();
+        if (theMEdges.Contains(anIm) && aMImFence.Add(anIm)) {
+          BRep_Builder().Add(anImages, anIm);
+          aLEImages.Append(anIm);
+        }
+      }
+    }
+    //
+    // find alone vertices
+    TopoDS_Vertex aVW1, aVW2;
+    TopTools_IndexedDataMapOfShapeListOfShape aDMImVE;
+    TopExp::MapShapesAndAncestors(anImages, TopAbs_VERTEX, TopAbs_EDGE, aDMImVE);
+    //
+    TopTools_ListOfShape aLVAlone;
+    Standard_Integer aNb = aDMImVE.Extent();
+    for (i = 1; i <= aNb; ++i) {
+      const TopTools_ListOfShape& aLImE = aDMImVE(i);
+      if (aLImE.Extent() == 1) {
+        aLVAlone.Append(aDMImVE.FindKey(i));
+      }
+    }
+    //
+    if (aLVAlone.Extent() > 1) {
+      aVW1 = *(TopoDS_Vertex*)&aLVAlone.First();
+      aVW2 = *(TopoDS_Vertex*)&aLVAlone.Last();
+      //
+      // check distances
+      const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
+      const gp_Pnt& aPW1 = BRep_Tool::Pnt(aVW1);
+      const gp_Pnt& aPW2 = BRep_Tool::Pnt(aVW2);
+      //
+      Standard_Real aDist1 = aPI1.SquareDistance(aPW1);
+      Standard_Real aDist2 = aPI1.SquareDistance(aPW2);
+      //
+      if (aDist1 < aDist2) {
+        aVI1 = aVW1;
+        aVI2 = aVW2;
+      }
+      else {
+        aVI1 = aVW2;
+        aVI2 = aVW1;
+      }
+    }
+  }
+  else {
+    aLEImages.Append(theEIm);
+  }
+  //
+  // Find edges connected to these vertices
+  const TopTools_ListOfShape& aLIE1 = theDMVE.FindFromKey(aVI1);
+  const TopTools_ListOfShape& aLIE2 = theDMVE.FindFromKey(aVI2);
+  //
+  // Find vertices on the original face corresponding to vertices on the offset edge
+  //
+  // find original edges for both lists
+  TopTools_ListOfShape aLOE1, aLOE2;
+  for (i = 0; i < 2; ++i) {
+    const TopTools_ListOfShape& aLIE = !i ? aLIE1 : aLIE2;
+    TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
+    //
+    TopTools_MapOfShape aMFence;
+    //
+    TopTools_ListIteratorOfListOfShape aItLIE(aLIE);
+    for (; aItLIE.More(); aItLIE.Next()) {
+      const TopoDS_Shape& aEI = aItLIE.Value();
+      if (theEdgesOrigins.IsBound(aEI)) {
+        const TopTools_ListOfShape& aLEOrigins = theEdgesOrigins.Find(aEI);
+        //
+        TopTools_ListIteratorOfListOfShape aItLOE(aLEOrigins);
+        for (; aItLOE.More(); aItLOE.Next()) {
+          const TopoDS_Shape& aEO = aItLOE.Value();
+          if (aEO.ShapeType() == TopAbs_EDGE && aMFence.Add(aEO)) {
+            TopoDS_Shape aEOin;
+            if (FindShape(aEO, theFOr, aEOin)) {
+              aLOE.Append(aEO);
+            }
+          }
+        }
+      }
+    }
+  }
+  //
+  if (aLOE1.Extent() < 2 || aLOE2.Extent() < 2) {
+    return Standard_False;
+  }
+  //
+  // find vertices common for all edges in the lists
+  for (i = 0; i < 2; ++i) {
+    const TopTools_ListOfShape& aLOE = !i ? aLOE1 : aLOE2;
+    TopoDS_Vertex& aVO = !i ? aVO1 : aVO2;
+    //
+    const TopoDS_Shape& aEO = aLOE.First();
+    TopExp_Explorer aExpV(aEO, TopAbs_VERTEX);
+    for (; aExpV.More(); aExpV.Next()) {
+      const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&aExpV.Current();
+      //
+      Standard_Boolean bVertValid = Standard_True;
+      TopTools_ListIteratorOfListOfShape aItLOE(aLOE);
+      for (aItLOE.Next(); aItLOE.More(); aItLOE.Next()) {
+        const TopoDS_Shape& aEOx = aItLOE.Value();
+        TopExp_Explorer aExpVx(aEOx, TopAbs_VERTEX);
+        for (; aExpVx.More(); aExpVx.Next()) {
+          const TopoDS_Shape& aVx = aExpVx.Current();
+          if (aVx.IsSame(aV)) {
+            break;
+          }
+        }
+        //
+        if (!aExpVx.More()) {
+          bVertValid = Standard_False;
+          break;
+        }
+      }
+      //
+      if (bVertValid) {
+        aVO = aV;
+        break;
+      }
+    }
+  }
+  //
+  if (aVO1.IsNull() || aVO2.IsNull() || aVO1.IsSame(aVO2)) {
+    return Standard_False;
+  }
+  //
+  // check positions of the offset and original vertices
+  const gp_Pnt& aPI1 = BRep_Tool::Pnt(aVI1);
+  const gp_Pnt& aPI2 = BRep_Tool::Pnt(aVI2);
+  const gp_Pnt& aPO1 = BRep_Tool::Pnt(aVO1);
+  const gp_Pnt& aPO2 = BRep_Tool::Pnt(aVO2);
+  //
+  gp_Vec aVI(aPI1, aPI2);
+  gp_Vec aVO(aPO1, aPO2);
+  //
+  Standard_Real anAngle = aVI.Angle(aVO);
+  Standard_Boolean bInverted = Abs(anAngle - M_PI) < 1.e-4;
+  if (bInverted) {
+    TopTools_ListIteratorOfListOfShape aItLEIm(aLEImages);
+    for (; aItLEIm.More(); aItLEIm.Next()) {
+      const TopoDS_Shape& aEInvr = aItLEIm.Value();
+      theMEInverted.Add(aEInvr);
+    }
+  }
+  return bInverted;
+}
+
+//=======================================================================
+//function : RemoveInvalidSplitsByInvertedEdges
+//purpose  : Looking for the invalid faces containing inverted edges
+//           that can be safely removed
+//=======================================================================
+void RemoveInvalidSplitsByInvertedEdges(const TopTools_MapOfShape& theMEInverted,
+                                        TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                                        TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                                        TopTools_IndexedMapOfShape& theMERemoved)
+{
+  if (theMEInverted.IsEmpty()) {
+    return;
+  }
+  //
+  // check the faces on regularity, i.e. the splits of the same face
+  // should not be connected only by vertex. Such irregular splits
+  // will have to be rebuilt and cannot be removed.
+  //
+  TopTools_MapOfShape aMEAvoid;
+  TopTools_DataMapOfShapeListOfShape aDMVF;
+  Standard_Integer aNb = theFImages.Extent(), i;
+  for (i = 1; i <= aNb; ++i) {
+    const TopTools_ListOfShape& aLFIm = theFImages(i);
+    //
+    TopoDS_Compound aCFIm;
+    BRep_Builder().MakeCompound(aCFIm);
+    //
+    TopTools_DataMapOfShapeListOfShape aDMEF;
+    TopTools_ListIteratorOfListOfShape aIt(aLFIm);
+    for (; aIt.More(); aIt.Next()) {
+      const TopoDS_Shape& aF = aIt.Value();
+      BRep_Builder().Add(aCFIm, aF);
+      //
+      // make a map to use only outer edges
+      TopExp_Explorer aExp(aF, TopAbs_EDGE);
+      for (; aExp.More(); aExp.Next()) {
+        const TopoDS_Shape& aE = aExp.Current();
+        //
+        TopTools_ListOfShape *pLF = aDMEF.ChangeSeek(aE);
+        if (!pLF) {
+          TopTools_ListOfShape aLF;
+          aLF.Append(aF);
+          aDMEF.Bind(aE, aLF);
+        }
+        else {
+          pLF->Append(aF);
+          // internal edges should not be used
+          aMEAvoid.Add(aE);
+        }
+      }
+      //
+      // fill connection map of the vertices of inverted edges to faces
+      aExp.Init(aF, TopAbs_VERTEX);
+      for (; aExp.More(); aExp.Next()) {
+        const TopoDS_Shape& aV = aExp.Current();
+        //
+        TopTools_ListOfShape *pLF = aDMVF.ChangeSeek(aV);
+        if (!pLF) {
+          TopTools_ListOfShape aLF;
+          aLF.Append(aF);
+          aDMVF.Bind(aV, aLF);
+        }
+        else {
+          AppendToList(*pLF, aF);
+        }
+      }
+    }
+    //
+    // for the splits to be regular they should form only one block
+    TopTools_ListOfShape aLCBF;
+    BOPTools_AlgoTools::MakeConnexityBlocks(aCFIm, TopAbs_EDGE, TopAbs_FACE, aLCBF);
+    //
+    if (aLCBF.Extent() >  1) {
+      // non of these edges should be removed
+      TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDM(aDMEF);
+      for (; aItDM.More(); aItDM.Next()) {
+        aMEAvoid.Add(aItDM.Key());
+      }
+    }
+  }
+  //
+  // all edges not included in aMEAvoid can be removed
+  TopTools_MapOfShape aMERem;
+  TopTools_MapIteratorOfMapOfShape aItM(theMEInverted);
+  for (; aItM.More(); aItM.Next()) {
+    const TopoDS_Shape& aE = aItM.Value();
+    if (!aMEAvoid.Contains(aE)) {
+      TopoDS_Iterator aIt(aE);
+      for (; aIt.More(); aIt.Next()) {
+        const TopoDS_Shape& aV = aIt.Value();
+        const TopTools_ListOfShape *pLF = aDMVF.Seek(aV);
+        if (pLF && (pLF->Extent() > 3)) {
+          aMERem.Add(aE);
+          break;
+        }
+      }
+    }
+  }
+  //
+  if (aMERem.IsEmpty()) {
+    return;
+  }
+  //
+  // all invalid faces containing these edges can be removed
+  TopTools_IndexedDataMapOfShapeListOfShape aInvFaces;
+  TopTools_MapOfShape aMFRem;
+  TopTools_IndexedMapOfShape aMFToUpdate;
+  aNb = theInvFaces.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aF = theInvFaces.FindKey(i);
+    TopTools_ListOfShape& aLFIm = theInvFaces(i);
+    //
+    TopTools_ListIteratorOfListOfShape aIt(aLFIm);
+    for (; aIt.More(); ) {
+      const TopoDS_Shape& aFIm = aIt.Value();
+      //
+      // to be removed the face should have at least two not connected
+      // inverted edges
+      TopoDS_Compound aCEInv;
+      BRep_Builder().MakeCompound(aCEInv);
+      TopExp_Explorer aExp(aFIm, TopAbs_EDGE);
+      for (; aExp.More(); aExp.Next()) {
+        const TopoDS_Shape& aE = aExp.Current();
+        //
+        if (aMERem.Contains(aE)) {
+          BRep_Builder().Add(aCEInv, aE);
+        }
+      }
+      //
+      // check connectivity
+      TopTools_ListOfShape aLCBE;
+      BOPTools_AlgoTools::MakeConnexityBlocks(aCEInv, TopAbs_VERTEX, TopAbs_EDGE, aLCBE);
+      //
+      if (aLCBE.Extent() >= 2) {
+        aMFToUpdate.Add(aF);
+        aMFRem.Add(aFIm);
+        aLFIm.Remove(aIt);
+      }
+      else {
+        aIt.Next();
+      }
+    }
+    //
+    if (aLFIm.Extent()) {
+      aInvFaces.Add(aF, aLFIm);
+    }
+  }
+  //
+  if (aMFRem.IsEmpty()) {
+    return;
+  }
+  //
+  theInvFaces = aInvFaces;
+  // remove from splits
+  aNb = aMFToUpdate.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aF = aMFToUpdate(i);
+    TopTools_ListOfShape& aLFIm = theFImages.ChangeFromKey(aF);
+    //
+    TopTools_ListIteratorOfListOfShape aIt(aLFIm);
+    for (; aIt.More(); ) {
+      const TopoDS_Shape& aFIm = aIt.Value();
+      if (aMFRem.Contains(aFIm)) {
+        TopExp::MapShapes(aFIm, TopAbs_EDGE, theMERemoved);
+        aLFIm.Remove(aIt);
+      }
+      else {
+        aIt.Next();
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : RemoveInvalidSplitsFromValid
+//purpose  : Removing invalid splits of faces from valid
+//=======================================================================
+void RemoveInvalidSplitsFromValid(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                                  const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                                  const TopTools_MapOfShape& theMEInverted,
+                                  TopTools_IndexedDataMapOfShapeListOfShape& theFImages)
+{
+  // Decide whether to remove the found invalid faces or not.
+  // The procedure is the following:
+  // 1. Make connexity blocks from invalid faces;
+  // 2. Find free edges in this blocks;
+  // 3. If all free edges are valid for the faces - remove block.
+  //
+  TopTools_MapOfShape aMFence, aMFToRem;
+  TopoDS_Compound aCFInv;
+  BRep_Builder aBB;
+  aBB.MakeCompound(aCFInv);
+  TopTools_ListIteratorOfListOfShape aItLF;
+  //
+  // make compound of invalid faces
+  TopTools_DataMapOfShapeShape aDMIFOF;
+  Standard_Integer i, aNb = theInvFaces.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aF = theInvFaces.FindKey(i);
+    // artificially invalid faces should not be removed
+    if (theArtInvFaces.IsBound(aF)) {
+      continue;
+    }
+    const TopTools_ListOfShape& aLFInv = theInvFaces(i);
+    aItLF.Initialize(aLFInv);
+    for (; aItLF.More(); aItLF.Next()) {
+      const TopoDS_Shape& aFIm = aItLF.Value();
+      if (aMFence.Add(aFIm)) {
+        aBB.Add(aCFInv, aFIm);
+        aDMIFOF.Bind(aFIm, aF);
+      }
+    }
+  }
+  //
+  // make connexity blocks
+  TopTools_ListOfShape aLCBInv;
+  BOPTools_AlgoTools::MakeConnexityBlocks(aCFInv, TopAbs_EDGE, TopAbs_FACE, aLCBInv);
+  //
+  // analyze each block
+  aItLF.Initialize(aLCBInv);
+  for (; aItLF.More(); aItLF.Next()) {
+    const TopoDS_Shape& aCB = aItLF.Value();
+    //
+    // if connexity block contains only one face - it should be removed;
+    TopExp_Explorer aExp(aCB, TopAbs_FACE);
+    aExp.Next();
+    if (aExp.More()) {
+      // check if there are valid images left
+      aExp.Init(aCB, TopAbs_FACE);
+      for (; aExp.More(); aExp.Next()) {
+        const TopoDS_Shape& aFIm = aExp.Current();
+        const TopoDS_Shape& aF = aDMIFOF.Find(aFIm);
+        //
+        const TopTools_ListOfShape& aLFIm = theFImages.FindFromKey(aF);
+        const TopTools_ListOfShape& aLFInv = theInvFaces.FindFromKey(aF);
+        //
+        if (aLFIm.Extent() == aLFInv.Extent()) {
+          break;
+        }
+      }
+    }
+    //
+    if (!aExp.More()) {
+      aExp.Init(aCB, TopAbs_FACE);
+      for (; aExp.More(); aExp.Next()) {
+        const TopoDS_Shape& aF = aExp.Current();
+        aMFToRem.Add(aF);
+      }
+      continue;
+    }
+    //
+    // remove faces connected by inverted edges
+    TopTools_IndexedDataMapOfShapeListOfShape aDMEF;
+    TopExp::MapShapesAndAncestors(aCB, TopAbs_EDGE, TopAbs_FACE, aDMEF);
+    //
+    aExp.Init(aCB, TopAbs_FACE);
+    for (; aExp.More(); aExp.Next()) {
+      const TopoDS_Shape& aFCB = aExp.Current();
+      //
+      TopExp_Explorer aExpE(aFCB, TopAbs_EDGE);
+      for (; aExpE.More(); aExpE.Next()) {
+        const TopoDS_Shape& aECB = aExpE.Current();
+        if (aDMEF.FindFromKey(aECB).Extent() > 1) {
+          if (!theMEInverted.Contains(aECB)) {
+            break;
+          }
+        }
+      }
+      //
+      if (!aExpE.More()) {
+        aMFToRem.Add(aFCB);
+      }
+    }
+  }
+  //
+  if (aMFToRem.Extent()) {
+    // remove invalid faces from images
+    aNb = theInvFaces.Extent();
+    for (i = 1; i <= aNb; ++i) {
+      const TopoDS_Shape& aF = theInvFaces.FindKey(i);
+      TopTools_ListOfShape& aLFImages = theFImages.ChangeFromKey(aF);
+      aItLF.Initialize(aLFImages);
+      for (; aItLF.More();) {
+        const TopoDS_Shape& aFIm = aItLF.Value();
+        if (aMFToRem.Contains(aFIm)) {
+          aLFImages.Remove(aItLF);
+        }
+        else {
+          aItLF.Next();
+        }
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : RemoveInsideFaces
+//purpose  : Looking for the inside faces that can be safely removed
+//=======================================================================
+void RemoveInsideFaces(TopTools_IndexedDataMapOfShapeListOfShape& theFImages,
+                       TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                       const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                       const TopTools_IndexedMapOfShape& theInvEdges,
+                       const TopTools_IndexedMapOfShape& theMFToCheckInt,
+                       TopTools_DataMapOfShapeListOfShape& theSSInterfs,
+                       TopTools_IndexedMapOfShape& theMERemoved,
+                       TopoDS_Shape& theSolids)
+{
+  BOPCol_ListOfShape aLS;
+  TopTools_MapOfShape aMFence;
+  TopTools_IndexedMapOfShape aMFInv;
+  TopTools_ListIteratorOfListOfShape aItLF;
+  TopTools_DataMapOfShapeShape aDMFImF;
+  //
+  Standard_Integer i, aNb = theFImages.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aF = theFImages.FindKey(i);
+    // to avoid intersection of the splits of the same
+    // offset faces among themselves make compound of the
+    // splits and use it as one argument
+    TopoDS_Compound aCFImi;
+    BRep_Builder().MakeCompound(aCFImi);
+    //
+    for (Standard_Integer j = 0; j < 2; ++j) {
+      const TopTools_ListOfShape* pLFSp = !j ? theInvFaces.Seek(aF) : &theFImages(i);
+      if (!pLFSp) {
+        continue;
+      }
+      //
+      aItLF.Initialize(*pLFSp);
+      for (; aItLF.More(); aItLF.Next()) {
+        const TopoDS_Shape& aFIm = aItLF.Value();
+        if (aMFence.Add(aFIm)) {
+          BRep_Builder().Add(aCFImi, aFIm);
+          aDMFImF.Bind(aFIm, aF);
+          if (!j) {
+            aMFInv.Add(aFIm);
+          }
+        }
+      }
+    }
+    //
+    aLS.Append(aCFImi);
+  }
+  //
+  // to make the solids more complete add for intersection also the faces
+  // consisting only of invalid edges and not included into splits
+  aNb = theMFToCheckInt.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aFSp = theMFToCheckInt(i);
+    if (aMFence.Add(aFSp)) {
+      aLS.Append(aFSp);
+    }
+  }
+  //
+  BOPAlgo_MakerVolume aMV;
+  aMV.SetArguments(aLS);
+  aMV.SetIntersect(Standard_True);
+  aMV.Perform();
+  //
+  // get shapes connection for using in the rebuilding process
+  // for the cases in which some of the intersection left undetected
+  ShapesConnections(theInvFaces, theInvEdges, aDMFImF, aMV, theSSInterfs);
+  //
+  // find faces to remove
+  const TopoDS_Shape& aSols = aMV.Shape();
+  //
+  TopTools_IndexedDataMapOfShapeListOfShape aDMFS;
+  TopExp::MapShapesAndAncestors(aSols, TopAbs_FACE, TopAbs_SOLID, aDMFS);
+  //
+  aNb = aDMFS.Extent();
+  if (!aNb) {
+    return;
+  }
+  //
+  // To use the created solids for classifications, firstly, it is necessary
+  // to check them on validity - the created solids should be complete,
+  // i.e. all faces should be included.
+  //
+  // Check completeness
+  if (aMV.HasDeleted()) {
+    // perform additional check on faces
+    aNb = theFImages.Extent();
+    for (i = 1; i <= aNb; ++i) {
+      const TopTools_ListOfShape& aLFIm = theFImages(i);
+      if (aLFIm.IsEmpty()) {
+        continue;
+      }
+      //
+      aItLF.Initialize(aLFIm);
+      for (; aItLF.More(); aItLF.Next()) {
+        const TopoDS_Shape& aFIm = aItLF.Value();
+        if (!aMV.IsDeleted(aFIm)) {
+          break;
+        }
+      }
+      //
+      if (!aItLF.More()) {
+        return;
+      }
+    }
+  }
+  //
+  TopTools_MapOfShape aMFToRem;
+  aNb = aDMFS.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopTools_ListOfShape& aLSol = aDMFS(i);
+    if (aLSol.Extent() > 1) {
+      const TopoDS_Shape& aFIm = aDMFS.FindKey(i);
+      aMFToRem.Add(aFIm);
+    }
+  }
+  //
+  // update invalid faces with images
+  aNb = aMFInv.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aFInv = aMFInv(i);
+    const TopTools_ListOfShape& aLFInvIm = aMV.Modified(aFInv);
+    TopTools_ListIteratorOfListOfShape aItLFInvIm(aLFInvIm);
+    for (; aItLFInvIm.More(); aItLFInvIm.Next()) {
+      const TopoDS_Shape& aFInvIm = aItLFInvIm.Value();
+      aMFInv.Add(aFInvIm);
+    }
+  }
+  //
+  TopoDS_Compound aSolids;
+  BRep_Builder().MakeCompound(aSolids);
+  //
+  TopExp_Explorer aExpS(aSols, TopAbs_SOLID);
+  for (; aExpS.More(); aExpS.Next()) {
+    const TopoDS_Shape& aSol = aExpS.Current();
+    //
+    Standard_Boolean bAllInv(Standard_True), bAllRemoved(Standard_True);
+
+    TopExp_Explorer aExpF(aSol, TopAbs_FACE);
+    for (; aExpF.More(); aExpF.Next()) {
+      const TopoDS_Shape& aFS = aExpF.Current();
+      //
+      if (aFS.Orientation() == TopAbs_INTERNAL) {
+        aMFToRem.Add(aFS);
+      }
+      //
+      bAllRemoved = bAllRemoved && aMFToRem.Contains(aFS);
+      bAllInv = bAllInv && (aMFToRem.Contains(aFS) || aMFInv.Contains(aFS));
+    }
+    //
+    if (bAllInv && !bAllRemoved) {
+      // remove invalid faces but keep those that have already been marked for removal
+      TopExp_Explorer aExpF(aSol, TopAbs_FACE);
+      for (; aExpF.More(); aExpF.Next()) {
+        const TopoDS_Shape& aFS = aExpF.Current();
+        //
+        if (aMFToRem.Contains(aFS)) {
+          aMFToRem.Remove(aFS);
+        }
+        else {
+          aMFToRem.Add(aFS);
+        }
+      }
+    }
+    else {
+      BRep_Builder().Add(aSolids, aSol);
+      theSolids = aSolids;
+    }
+  }
+  //
+  // remove newly found internal faces
+  RemoveValidSplits(aMFToRem, theFImages, aMV, theMERemoved);
+  RemoveInvalidSplits(aMFToRem, theArtInvFaces, theInvEdges, theInvFaces, aMV, theMERemoved);
+}
+
+//=======================================================================
+//function : ShapesConnections
+//purpose  : Looking for the connections between faces not to miss
+//           some necessary intersection
+//=======================================================================
+void ShapesConnections(const TopTools_IndexedDataMapOfShapeListOfShape& theInvFaces,
+                       const TopTools_IndexedMapOfShape& theInvEdges,
+                       const TopTools_DataMapOfShapeShape& theDMFOr,
+                       BOPAlgo_Builder& theBuilder,
+                       TopTools_DataMapOfShapeListOfShape& theSSInterfs)
+{
+  // update invalid edges with images and keep connection to original edge
+  TopTools_DataMapOfShapeListOfShape aDMEOr;
+  Standard_Integer i, aNb = theInvEdges.Extent();
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aEInv = theInvEdges(i);
+    const TopTools_ListOfShape& aLEIm = theBuilder.Modified(aEInv);
+    if (aLEIm.IsEmpty()) {
+      aDMEOr.Bound(aEInv, TopTools_ListOfShape())->Append(aEInv);
+      continue;
+    }
+    //
+    TopTools_ListIteratorOfListOfShape aItLEIm(aLEIm);
+    for (; aItLEIm.More(); aItLEIm.Next()) {
+      const TopoDS_Shape& aEIm = aItLEIm.Value();
+      //
+      TopTools_ListOfShape* pLEOr = aDMEOr.ChangeSeek(aEIm);
+      if (!pLEOr) {
+        pLEOr = aDMEOr.Bound(aEIm, TopTools_ListOfShape());
+      }
+      AppendToList(*pLEOr, aEInv);
+    }
+  }
+  //
+  // get shapes connections for using in the rebuilding process
+  const BOPDS_PDS& pDS = theBuilder.PDS();
+  // analyze all Face/Face intersections
+  const BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
+  Standard_Integer iInt, aNbFF = aFFs.Extent();
+  for (iInt = 0; iInt < aNbFF; ++iInt) {
+    const BOPDS_InterfFF& aFF = aFFs(iInt);
+    const BOPDS_VectorOfCurve& aVNC = aFF.Curves();
+    Standard_Integer aNbC = aVNC.Extent();
+    if (!aNbC) {
+      continue;
+    }
+    //
+    const TopoDS_Shape& aFIm1 = pDS->Shape(aFF.Index1());
+    const TopoDS_Shape& aFIm2 = pDS->Shape(aFF.Index2());
+    //
+    const TopoDS_Shape* pF1 = theDMFOr.Seek(aFIm1);
+    const TopoDS_Shape* pF2 = theDMFOr.Seek(aFIm2);
+    //
+    if (!pF1 || !pF2) {
+      continue;
+    }
+    //
+    if (pF1->IsSame(*pF2)) {
+      continue;
+    }
+    //
+    Standard_Boolean bInv1 = theInvFaces.Contains(*pF1);
+    Standard_Boolean bInv2 = theInvFaces.Contains(*pF2);
+    //
+    if (!bInv1 && !bInv2) {
+      continue;
+    }
+    //
+    // check if it is real Face/Face intersection
+    TopTools_MapOfShape aMEInt;
+    for (Standard_Integer iC = 0; iC < aNbC; ++iC) {
+      const BOPDS_Curve& aNC = aVNC(iC);
+      const BOPDS_ListOfPaveBlock& aLPB = aNC.PaveBlocks();
+      BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
+      for (; aItLPB.More(); aItLPB.Next()) {
+        const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
+        Standard_Integer nEInt;
+        if (aPB->HasEdge(nEInt)) {
+          const TopoDS_Shape& aEInt = pDS->Shape(nEInt);
+          aMEInt.Add(aEInt);
+        }
+      }
+    }
+    //
+    if (aMEInt.IsEmpty()) {
+      continue;
+    }
+    //
+    // check if invalid edges of the face are in the same splits with intersection edges
+    for (Standard_Integer i = 0; i < 2; ++i) {
+      if ((!i && !bInv1) || (i && !bInv2)) {
+        continue;
+      }
+      //
+      const TopoDS_Shape& aF = !i ? *pF1 : *pF2;
+      const TopoDS_Shape& aFOp = !i ? *pF2 : *pF1;
+      const TopoDS_Shape& aFIm = !i ? aFIm1 : aFIm2;
+      //
+      Standard_Boolean bFound = Standard_False;
+      //
+      TopTools_ListOfShape aLFIm = theBuilder.Modified(aFIm);
+      if (aLFIm.IsEmpty()) {
+        aLFIm.Append(aFIm);
+      }
+      //
+      TopTools_ListIteratorOfListOfShape aItLFIm(aLFIm);
+      for (; aItLFIm.More(); aItLFIm.Next()) {
+        const TopoDS_Shape& aFImIm = aItLFIm.Value();
+        //
+        Standard_Boolean bInv(Standard_False), bInt(Standard_False);
+        TopExp_Explorer aExpE(aFImIm, TopAbs_EDGE);
+        for (; aExpE.More(); aExpE.Next()) {
+          const TopoDS_Shape& aE = aExpE.Current();
+          if (!bInv) {
+            bInv = aDMEOr.IsBound(aE);
+          }
+          if (!bInt) {
+            bInt = aMEInt.Contains(aE);
+          }
+          if (bInv && bInt) {
+            break;
+          }
+        }
+        //
+        if (!bInt || !bInv) {
+          continue;
+        }
+        //
+        bFound = Standard_True;
+        //
+        // append opposite face to all invalid edges in the split
+        aExpE.Init(aFImIm, TopAbs_EDGE);
+        for (; aExpE.More(); aExpE.Next()) {
+          const TopoDS_Shape& aE = aExpE.Current();
+          const TopTools_ListOfShape* pLEOr = aDMEOr.Seek(aE);
+          if (!pLEOr) {
+            continue;
+          }
+          //
+          TopTools_ListIteratorOfListOfShape aItLE(*pLEOr);
+          for (; aItLE.More(); aItLE.Next()) {
+            const TopoDS_Shape& aEOr = aItLE.Value();
+            TopTools_ListOfShape *pLFE = theSSInterfs.ChangeSeek(aEOr);
+            if (!pLFE) {
+              pLFE = theSSInterfs.Bound(aEOr, TopTools_ListOfShape());
+            }
+            AppendToList(*pLFE, aFOp);
+          }
+        }
+      }
+      if (bFound) {
+        // save connection between offset faces
+        TopTools_ListOfShape *pLF = theSSInterfs.ChangeSeek(aF);
+        if (!pLF) {
+          pLF = theSSInterfs.Bound(aF, TopTools_ListOfShape());
+        }
+        AppendToList(*pLF, aFOp);
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : RemoveValidSplits
+//purpose  : Removing valid splits according to results of intersection
+//=======================================================================
+void RemoveValidSplits(const TopTools_MapOfShape& theSpRem,
+                       TopTools_IndexedDataMapOfShapeListOfShape& theImages,
+                       BOPAlgo_Builder& theGF,
+                       TopTools_IndexedMapOfShape& theMERemoved)
+{
+  Standard_Integer i, aNb = theImages.Extent();
+  if (!aNb) {
+    return;
+  }
+  //
+  for (i = 1; i <= aNb; ++i) {
+    TopTools_ListOfShape& aLSIm = theImages(i);
+    TopTools_ListIteratorOfListOfShape aIt(aLSIm);
+    for (; aIt.More(); ) {
+      const TopoDS_Shape& aSIm = aIt.Value();
+      if (theSpRem.Contains(aSIm)) {
+        TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
+        aLSIm.Remove(aIt);
+        continue;
+      }
+      //
+      // check if all its images are have to be removed
+      const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm);
+      if (aLSImIm.Extent()) {
+        Standard_Boolean bAllRem = Standard_True;
+        TopTools_ListIteratorOfListOfShape aIt1(aLSImIm);
+        for (; aIt1.More(); aIt1.Next()) {
+          const TopoDS_Shape& aSImIm = aIt1.Value();
+          if (theSpRem.Contains(aSImIm)) {
+            TopExp::MapShapes(aSImIm, TopAbs_EDGE, theMERemoved);
+          }
+          else {
+            bAllRem = Standard_False;
+          }
+        }
+        //
+        if (bAllRem) {
+          TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
+          aLSIm.Remove(aIt);
+          continue;
+        }
+      }
+      aIt.Next();
+    }
+  }
+}
+
+//=======================================================================
+//function : RemoveInvalidSplits
+//purpose  : Removing invalid splits according to the results of intersection
+//=======================================================================
+void RemoveInvalidSplits(const TopTools_MapOfShape& theSpRem,
+                         const TopTools_DataMapOfShapeShape& theArtInvFaces,
+                         const TopTools_IndexedMapOfShape& theInvEdges,
+                         TopTools_IndexedDataMapOfShapeListOfShape& theImages,
+                         BOPAlgo_Builder& theGF,
+                         TopTools_IndexedMapOfShape& theMERemoved)
+{
+  Standard_Integer i, aNb = theImages.Extent();
+  if (!aNb) {
+    return;
+  }
+  //
+  for (i = 1; i <= aNb; ++i) {
+    const TopoDS_Shape& aS = theImages.FindKey(i);
+    Standard_Boolean bArt = theArtInvFaces.IsBound(aS);
+    //
+    TopTools_ListOfShape& aLSIm = theImages(i);
+    TopTools_ListIteratorOfListOfShape aIt(aLSIm);
+    for (; aIt.More();) {
+      const TopoDS_Shape& aSIm = aIt.Value();
+      if (theSpRem.Contains(aSIm)) {
+        TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
+        aLSIm.Remove(aIt);
+        continue;
+      }
+      //
+      // check if all its images are have to be removed
+      const TopTools_ListOfShape& aLSImIm = theGF.Modified(aSIm);
+      if (aLSImIm.IsEmpty()) {
+        aIt.Next();
+        continue;
+      }
+      //
+      Standard_Boolean bAllRem = Standard_True;
+      TopTools_IndexedMapOfShape aMERemoved;
+      TopTools_ListIteratorOfListOfShape aIt1(aLSImIm);
+      for (; aIt1.More(); aIt1.Next()) {
+        const TopoDS_Shape& aSImIm = aIt1.Value();
+        if (theSpRem.Contains(aSImIm)) {
+          TopExp::MapShapes(aSImIm, TopAbs_EDGE, aMERemoved);
+        }
+        else {
+          bAllRem = Standard_False;
+        }
+      }
+      //
+      if (bAllRem) {
+        aLSIm.Remove(aIt);
+        continue;
+      }
+      //
+      if (bArt) {
+        aIt.Next();
+        continue;
+      }
+      //
+      // remove the face from invalid if all invalid edges of this face
+      // have been marked for removal
+      TopExp_Explorer aExpE(aSIm, TopAbs_EDGE);
+      for (; aExpE.More(); aExpE.Next()) {
+        const TopoDS_Shape& aEInv = aExpE.Current();
+        if (theInvEdges.Contains(aEInv) && !aMERemoved.Contains(aEInv)) {
+          break;
+        }
+      }
+      if (!aExpE.More()) {
+        TopExp::MapShapes(aSIm, TopAbs_EDGE, theMERemoved);
+        aLSIm.Remove(aIt);
+      }
+      else {
+        aIt.Next();
+      }
+    }
+  }
+}
+
+//=======================================================================
+//function : FilterEdgesImages
+//purpose  : Updating the maps of images and origins of the offset edges
+//=======================================================================
+void FilterEdgesImages(const TopoDS_Shape& theS,
+                       TopTools_DataMapOfShapeListOfShape& theOEImages,
+                       TopTools_DataMapOfShapeListOfShape& theOEOrigins)
+{
+  // map edges
+  TopTools_IndexedMapOfShape aME;
+  TopExp::MapShapes(theS, TopAbs_EDGE, aME);
+  //
+  theOEOrigins.Clear();
+  TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItDM(theOEImages);
+  for (; aItDM.More(); aItDM.Next()) {
+    const TopoDS_Shape& aE = aItDM.Key();
+    TopTools_ListOfShape& aLEIm = aItDM.ChangeValue();
+    //
+    TopTools_ListIteratorOfListOfShape aIt(aLEIm);
+    for (; aIt.More(); ) {
+      const TopoDS_Shape& aEIm = aIt.Value();
+      // filter images
+      if (!aME.Contains(aEIm)) {
+        // remove the image
+        // edges with no images left should be kept in the map
+        // to avoid their usage when building the splits of faces
+        aLEIm.Remove(aIt);
+        continue;
+      }
+      //
+      // save origins
+      if (theOEOrigins.IsBound(aEIm)) {
+        AppendToList(theOEOrigins.ChangeFind(aEIm), aE);
+      }
+      else {
+        TopTools_ListOfShape aLOr;
+        aLOr.Append(aE);
+        theOEOrigins.Bind(aEIm, aLOr);
+      }
+      //
+      aIt.Next();
+    }
+  }
+}