642 if (
contains(connections, *longestConnect)) {
645 for (
auto & allconnection : allconnections) {
646 if (allconnection->Distance() >
length) {
647 if (!
contains(connections, allconnection)) {
648 longestOutside = allconnection;
654 longestOutside = *longestConnect;
658 Coord longestOutsideLength = longestOutside ? longestOutside->
Distance() : 0.0;
661 olddist -= (*longestConnect)->Distance();
666 for (
auto & segment : segments) {
667 segment.endbit = nEndBits++;
668 if (segment.nEndPoints == 4) {
669 segment.swapbit = nSwapBits++;
672 segment.swapbit = 31;
676 unsigned int swapMask = (1U << nSwapBits) - 1;
677 unsigned int endMask = (1U << nEndBits) - 1;
680 std::vector<int> permutation(segments.size());
684 bool improved =
false;
685 Coord distBest = olddist;
686 std::vector<int> permutationBest;
687 unsigned int iSwapBest;
688 unsigned int iEndBest;
694 unsigned int iSwap = 0;
697 unsigned int iEnd = 0;
700 Coord lengthTotal = 0;
702 Coord lengthLongest = longestOutsideLength;
706 for (
int & it : permutation) {
710 if (
length > lengthLongest) {
713 prevend = segments[it].GetEndPoint(iSwap, iEnd);
715 lengthTotal -= lengthLongest;
718 if (lengthTotal + 1e-6 < distBest) {
720 distBest = lengthTotal;
721 permutationBest = permutation;
727 for (
int & it : permutation) {
730 DebugTrace2TSP((
"IMP 0F=%d %d %.6lf", thisbeg->group->index, thisbeg->indexInGroup,
Geom::distance(thisbeg->point, prevend->
point)));
732 prevend = segments[it].GetEndPoint(iSwap, iEnd);
740 }
while (iEnd & endMask);
742 }
while (iSwap & swapMask);
744 }
while (std::next_permutation(permutation.begin() + 1, permutation.end()));
747 DebugTrace2TSP((
"Improvement %lf->%lf in %d", olddist, distBest, nTrials));
750 for (std::vector<OrderingGroupConnection *>::iterator it = connections.begin(); it != connections.end(); ++it) {
751 DebugTrace2TSP((
"WAS 0F=%d %d %.6lf", (*it)->points[0]->group->index, (*it)->points[0]->indexInGroup, (*it)->Distance()));
752 DebugTrace2TSP((
"WAS 0T=%d %d %.6lf", (*it)->points[1]->group->index, (*it)->points[1]->indexInGroup, (*it)->Distance()));
754 DebugTrace2TSP((
"OLDDIST %.6lf delta %.6lf", olddist, olddist - (*longestConnect)->Distance()));
755 DebugTrace2TSP((
"LONG =%d %d %.6lf", (*longestConnect)->points[0]->group->index, (*longestConnect)->points[0]->indexInGroup, (*longestConnect)->Distance()));
756 DebugTrace2TSP((
"LONG =%d %d %.6lf", (*longestConnect)->points[1]->group->index, (*longestConnect)->points[1]->indexInGroup, (*longestConnect)->Distance()));
758 int perm = permutationBest.back();
760 for (std::vector<OrderingGroupConnection *>::iterator it = connections.begin(); it != connections.end(); ++it) {
761 (*it)->Connect(1, segments[ perm ].GetEndPoint(iSwapBest, iEndBest));
762 perm = permutationBest[ it - connections.begin() ];
763 (*it)->Connect(0, segments[ perm ].GetBeginPoint(iSwapBest, iEndBest));
767 for (std::vector<OrderingGroupConnection *>::iterator it = connections.begin(); it != connections.end(); ++it) {
768 DebugTrace2TSP((
"IS 0F=%d %d %.6lf", (*it)->points[0]->group->index, (*it)->points[0]->indexInGroup, (*it)->Distance()));
769 DebugTrace2TSP((
"IS 0T=%d %d %.6lf", (*it)->points[1]->group->index, (*it)->points[1]->indexInGroup, (*it)->Distance()));
772 (*longestConnect) = longestOutside;
773 for (
auto & connection : connections) {
774 if (connection->Distance() > (*longestConnect)->Distance()) {
775 *longestConnect = connection;
778 DebugTrace2TSP((
"LONG =%d %d %.6lf", (*longestConnect)->points[0]->group->index, (*longestConnect)->points[0]->indexInGroup, (*longestConnect)->Distance()));
779 DebugTrace2TSP((
"LONG =%d %d %.6lf", (*longestConnect)->points[1]->group->index, (*longestConnect)->points[1]->indexInGroup, (*longestConnect)->Distance()));
788 for (
auto & connection : connections) {
789 for (
auto pnt : connection->points) {
790 assert(pnt->connection == connection);
791 assert(pnt->connection->points[pnt->indexInConnection] == pnt);
792 assert(pnt->group->endpoints[pnt->indexInGroup] == pnt);
800 for (
unsigned int n = 0; n < connections.size(); n++) {
801 DebugTrace2TSP((
"Tour test 1 %p g=%d/%d c=%d/%d %p %p %.6lf %.3lf %.3lf %d %d %d",
current,
current->group->index,
current->indexInGroup,
current->connection->index,
current->indexInConnection,
current->connection->points[0],
current->connection->points[1],
current->connection->Distance(),
current->point.x(), 297 -
current->point.y(),
current->begin,
current->front,
current->group->items.size()));
804 longest1 = std::max(
length, longest1);
807 DebugTrace2TSP((
"Tour test 2 %p g=%d/%d c=%d/%d %p %p %.6lf %.3lf %.3lf %d %d %d",
current,
current->group->index,
current->indexInGroup,
current->connection->index,
current->indexInConnection,
current->connection->points[0],
current->connection->points[1],
current->connection->Distance(),
current->point.x(), 297 -
current->point.y(),
current->begin,
current->front,
current->group->items.size()));
811 assert(
current == connections.front()->points[0]);
816 current = connections.front()->points[0];
817 for (
unsigned int n = 0; n < connections.size(); n++) {
821 longest2 = std::max(
length, longest2);
824 assert(
current == connections.front()->points[0]);
826 DebugTrace1TSP((
"Tour length %.6lf(%.6lf) longest %.6lf(%.6lf) remaining %.6lf(%.6lf)", length1, length2, longest1, longest2, length1 - longest1, length2 - longest2));
868void OrderGroups(std::vector<OrderingGroup *> *groups,
const int nDims)
871 if (groups->size() <= 1) {
876 for (
auto & group : *groups) {
877 group->SetEndpoints();
881 for (std::vector<OrderingGroup *>::iterator itThis = groups->begin(); itThis != groups->end(); ++itThis) {
882 for (
int i = 0; i < (*itThis)->nEndPoints; i++) {
884 (*itThis)->endpoints[i]->nearest.reserve(4 * groups->size());
887 for (std::vector<OrderingGroup *>::iterator itNghb = groups->begin(); itNghb != groups->end(); ++itNghb) {
888 if (itThis != itNghb) {
889 (*itThis)->AddNeighbors(*itNghb);
893 for (
int i = 0; i < (*itThis)->nEndPoints; i++) {
901 std::vector<OrderingGroupConnection *> connections;
902 connections.reserve(groups->size());
912 for (
unsigned int nConnected = 0; nConnected < groups->size(); nConnected++) {
920 if (nConnected == groups->size() - 1) {
921 groups->front()->endpoints[0]->UnusePoint();
931 longestConnect = connections.back();
935 DebugTrace1TSP((
"Total jump distance %.3lf (closed)", total));
936 DebugTrace1TSP((
"Total jump distance %.3lf (open)", total - longestConnect->
Distance()));
945 int nImprovements = 0;
950 std::vector< std::vector<OrderingGroupConnection *>::iterator > iterators;
961 std::vector<OrderingSegment> segments(iterators.size());
962 std::vector<OrderingGroupConnection *> changedconnections;
963 changedconnections.reserve(3);
967 for (
size_t i = 0; i < iterators.size(); i++) {
968 dist += (*iterators[i])->Distance();
969 segments[i].AddPoint(prev->
points[1]);
970 segments[i].AddPoint((*iterators[i])->points[0]);
971 prev = *iterators[i];
972 changedconnections.push_back(*iterators[i]);
975 if (
FindShortestReconnect(segments, changedconnections, connections, &longestConnect, &total, dist)) {
984 }
while (improvement && nRuns < 10);
986 DebugTrace1TSP((
"Finished after %d rounds, %d trials, %d improvements", nRuns, nTrials, nImprovements));
990 std::vector<OrderingGroup *>
result;
991 result.reserve(groups->size());
997 for (
unsigned int n = 0; n < connections.size(); n++) {
1005 assert(
result.size() == groups->size());
1017 if (infos.size() < 3) {
1022 std::vector<OrderingInfoEx *> infoex;
1023 infoex.reserve(infos.size());
1025 for (std::vector<OrderingInfo>::const_iterator it = infos.begin(); it != infos.end();) {
1029 while (it != infos.end() && it->begOrig == infoex.back()->end.point) {
1030 infoex.back()->end.point = it->endOrig;
1031 infoex.back()->origIndices.push_back(it->index);
1038 for (std::vector<OrderingInfoEx *>::iterator it = infoex.begin(); it != infoex.end(); ++it) {
1039 (*it)->beg.FindNearest2(infoex);
1040 (*it)->end.FindNearest2(infoex);
1044 DebugTrace2((
"STEP1"));
1045 for (std::vector<OrderingInfoEx *>::iterator it = infoex.begin(); it != infoex.end(); ++it) {
1052 for (
auto & it : infoex) {
1053 it->beg.EnforceMutual();
1054 it->end.EnforceMutual();
1058 DebugTrace2((
"STEP2"));
1059 for (std::vector<OrderingInfoEx *>::iterator it = infoex.begin(); it != infoex.end(); ++it) {
1066 for (
auto & it : infoex) {
1067 it->beg.EnforceSymmetric(it->end);
1068 it->end.EnforceSymmetric(it->beg);
1072 DebugTrace2((
"STEP3"));
1073 for (std::vector<OrderingInfoEx *>::iterator it = infoex.begin(); it != infoex.end(); ++it) {
1080 std::vector<OrderingGroup *> groups;
1081 for (std::vector<OrderingInfoEx *>::iterator it = infoex.begin(); it != infoex.end(); ++it) {
1082 (*it)->MakeGroup(infoex, &groups);
1086 std::vector<OrderingInfo>
result;
1087 result.reserve(infos.size());
1089 for (
auto & it : infoex) {
1092 groups.back()->items.push_back(it);
1098 DebugTrace2((
"Ungrouped lines = %d", nUngrouped));
1099 DebugTrace2((
"%d Groups found", groups.size()));
1100 for (std::vector<OrderingGroup *>::iterator it = groups.begin(); it != groups.end(); ++it) {
1101 DebugTrace2((
"Group size %d", (*it)->items.size()));
1109 for (
auto & group : groups) {
1110 for (
unsigned int iItem = 0; iItem < group->items.size(); iItem++) {
1111 unsigned int iItemRev = group->revItemList ? group->items.size() - 1 - iItem : iItem;
1116 bool reverse = ((iItem & 1) == 0) == group->revItems;
1118 for (
int & origIndice :
item->origIndices) {
1119 result.push_back(infos[origIndice]);
1120 result.back().reverse =
false;
1123 for (std::vector<int>::reverse_iterator itOrig =
item->origIndices.rbegin(); itOrig !=
item->origIndices.rend(); ++itOrig) {
1124 result.push_back(infos[*itOrig]);
1125 result.back().reverse =
true;
1129 result.back().connect =
true;