Index: trunk/test/data/regress/18367/nocombine.osm
===================================================================
--- trunk/test/data/regress/18367/nocombine.osm	(revision 15574)
+++ trunk/test/data/regress/18367/nocombine.osm	(revision 15574)
@@ -0,0 +1,22 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<osm version='0.6' generator='JOSM' upload='false'>
+  <node id='-143178' action='modify' visible='true' lat='0.02196380816' lon='-0.02295195551' />
+  <node id='-143179' action='modify' visible='true' lat='0.02142481903' lon='0.00624329122' />
+  <node id='-143181' action='modify' visible='true' lat='0.02708420481' lon='0.01828071603' />
+  <node id='-143183' action='modify' visible='true' lat='0.03597752476' lon='0.01908919979' />
+  <node id='-143185' action='modify' visible='true' lat='0.03139611761' lon='0.0279825211' />
+  <node id='-143187' action='modify' visible='true' lat='-0.00696194343' lon='-0.00112289411' />
+  <way id='-143180' action='modify' visible='true'>
+    <nd ref='-143178' />
+    <nd ref='-143179' />
+    <nd ref='-143181' />
+    <nd ref='-143183' />
+    <nd ref='-143185' />
+  </way>
+  <way id='-143188' action='modify' visible='true'>
+    <nd ref='-143187' />
+    <nd ref='-143179' />
+    <nd ref='-143181' />
+    <nd ref='-143185' />
+  </way>
+</osm>
Index: trunk/test/data/regress/18367/silent-revert.osm
===================================================================
--- trunk/test/data/regress/18367/silent-revert.osm	(revision 15574)
+++ trunk/test/data/regress/18367/silent-revert.osm	(revision 15574)
@@ -0,0 +1,19 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<osm version='0.6' generator='JOSM'>
+  <node id='-103155' action='modify' visible='true' lat='-5.36336379389' lon='133.01215874827' />
+  <node id='-103156' action='modify' visible='true' lat='-5.36362512119' lon='133.01215243199' />
+  <node id='-103158' action='modify' visible='true' lat='-5.36358738945' lon='133.01222892916' />
+  <node id='-103160' action='modify' visible='true' lat='-5.36351747729' lon='133.01215503375' />
+  <node id='-103162' action='modify' visible='true' lat='-5.36353079183' lon='133.01211102527' />
+  <way id='-103157' action='modify' visible='true'>
+    <nd ref='-103155' />
+    <nd ref='-103160' />
+    <nd ref='-103156' />
+    <nd ref='-103158' />
+    <nd ref='-103160' />
+  </way>
+  <way id='-103163' action='modify' visible='true'>
+    <nd ref='-103162' />
+    <nd ref='-103160' />
+  </way>
+</osm>
Index: trunk/test/data/regress/18367/split-and-reverse.osm
===================================================================
--- trunk/test/data/regress/18367/split-and-reverse.osm	(revision 15574)
+++ trunk/test/data/regress/18367/split-and-reverse.osm	(revision 15574)
@@ -0,0 +1,19 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<osm version='0.6' generator='JOSM'>
+  <node id='-202121' action='modify' visible='true' lat='0.03681838663' lon='0.00176729094' />
+  <node id='-202123' action='modify' visible='true' lat='0.03673994598' lon='0.00172212813' />
+  <node id='-202125' action='modify' visible='true' lat='0.03669478317' lon='0.00181245375' />
+  <node id='-202127' action='modify' visible='true' lat='0.03675539641' lon='0.00186118205' />
+  <node id='-202129' action='modify' visible='true' lat='0.03645589572' lon='0.00185761657' />
+  <way id='-202132' action='modify' visible='true'>
+    <nd ref='-202121' />
+    <nd ref='-202123' />
+    <nd ref='-202125' />
+    <nd ref='-202127' />
+    <nd ref='-202121' />
+  </way>
+  <way id='-202133' action='modify' visible='true'>
+    <nd ref='-202125' />
+    <nd ref='-202129' />
+  </way>
+</osm>
Index: trunk/test/unit/org/openstreetmap/josm/actions/CombineWayActionTest.java
===================================================================
--- trunk/test/unit/org/openstreetmap/josm/actions/CombineWayActionTest.java	(revision 15563)
+++ trunk/test/unit/org/openstreetmap/josm/actions/CombineWayActionTest.java	(revision 15574)
@@ -3,12 +3,13 @@
 
 import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
 
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
@@ -19,5 +20,4 @@
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
-import org.openstreetmap.josm.data.osm.NodeGraph;
 import org.openstreetmap.josm.data.osm.NodePair;
 import org.openstreetmap.josm.data.osm.Way;
@@ -50,6 +50,5 @@
         try (InputStream is = TestUtils.getRegressionDataStream(11957, "data.osm")) {
             DataSet ds = OsmReader.parseDataSet(is, null);
-            NodeGraph graph = NodeGraph.createNearlyUndirectedGraphFromNodeWays(ds.getWays());
-            List<Node> path = graph.buildSpanningPathNoRemove();
+            List<Node> path = CombineWayAction.tryJoin(ds.getWays());
             assertEquals(10, path.size());
             Set<Long> firstAndLastObtained = new HashSet<>();
@@ -72,7 +71,6 @@
         try (InputStream is = TestUtils.getRegressionDataStream(18385, "data.osm")) {
             DataSet ds = OsmReader.parseDataSet(is, null);
-            NodeGraph graph = NodeGraph.createNearlyUndirectedGraphFromNodeWays(ds.getWays());
-            List<Node> path = graph.buildSpanningPathNoRemove();
-            assertNull(path);
+            List<Node> path = CombineWayAction.tryJoin(ds.getWays());
+            assertFalse(path.isEmpty());
         }
     }
@@ -91,9 +89,86 @@
             if (!selection.get(0).isNew())
                 Collections.reverse(selection);
-            NodeGraph graph = NodeGraph.createNearlyUndirectedGraphFromNodeWays(selection);
-            List<Node> path = graph.buildSpanningPathNoRemove();
-            assertTrue(path != null);
+            double expectedLen = getOriginalLength(selection);
+            List<Node> path = CombineWayAction.tryJoin(selection);
+            assertFalse(path.isEmpty());
+            Way combined = new Way(0);
+            combined.setNodes(path);
+            assertEquals(expectedLen, combined.getLength(), 0.01);
         }
     }
+
+    /**
+     * Non-regression test for bug #18367 (Lines cannot be combined when they share an overlapping segment)
+     * @throws IOException if any I/O error occurs
+     * @throws IllegalDataException if OSM parsing fails
+     */
+    @Test
+    public void testTicket18367() throws IOException, IllegalDataException {
+        try (InputStream is = TestUtils.getRegressionDataStream(18367, "nocombine.osm")) {
+            DataSet ds = OsmReader.parseDataSet(is, null);
+            ArrayList<Way> selection = new ArrayList<>(ds.getWays());
+            assertEquals(2, selection.size());
+            double expectedLen = getOriginalLength(selection);
+            List<Node> path = CombineWayAction.tryJoin(selection);
+            assertFalse(path.isEmpty());
+            Way combined = new Way(0);
+            combined.setNodes(path);
+            assertEquals(expectedLen, combined.getLength(), 1e-7);
+        }
+    }
+
+
+    /**
+     * Non-regression test for bug #18367
+     * @throws IOException if any I/O error occurs
+     * @throws IllegalDataException if OSM parsing fails
+     */
+    @Test
+    public void testTicket18367NeedsSplit() throws IOException, IllegalDataException {
+        try (InputStream is = TestUtils.getRegressionDataStream(18367, "split-and-reverse.osm")) {
+            DataSet ds = OsmReader.parseDataSet(is, null);
+            ArrayList<Way> selection = new ArrayList<>(ds.getWays());
+            assertEquals(2, selection.size());
+            double expectedLen = getOriginalLength(selection);
+            List<Node> path = CombineWayAction.tryJoin(selection);
+            assertFalse(path.isEmpty());
+            Way combined = new Way(0);
+            combined.setNodes(path);
+            assertEquals(expectedLen, combined.getLength(), 1e-7);
+            List<Way> reversedWays = new LinkedList<>();
+            List<Way> unreversedWays = new LinkedList<>();
+            CombineWayAction.detectReversedWays(selection, path, reversedWays, unreversedWays);
+            assertFalse(reversedWays.isEmpty());
+        }
+    }
+
+
+    /**
+     * Test for bad reverse way detection. See #18367
+     * @throws IOException if any I/O error occurs
+     * @throws IllegalDataException if OSM parsing fails
+     */
+    @Test
+    public void testDetectReversedWays() throws IOException, IllegalDataException {
+        try (InputStream is = TestUtils.getRegressionDataStream(18367, "silent-revert.osm")) {
+            DataSet ds = OsmReader.parseDataSet(is, null);
+            ArrayList<Way> selection = new ArrayList<>(ds.getWays());
+            assertEquals(2, selection.size());
+            // make sure that short way is first
+            if (selection.get(0).getNodesCount() != 2)
+                Collections.reverse(selection);
+            double expectedLen = getOriginalLength(selection);
+            List<Node> path = CombineWayAction.tryJoin(selection);
+            assertFalse(path.isEmpty());
+            Way combined = new Way(0);
+            combined.setNodes(path);
+            assertEquals(expectedLen, combined.getLength(), 1e-7);
+            List<Way> reversedWays = new LinkedList<>();
+            List<Way> unreversedWays = new LinkedList<>();
+            CombineWayAction.detectReversedWays(selection, path, reversedWays, unreversedWays);
+            assertFalse(reversedWays.contains(selection.get(0)));
+        }
+    }
+
 
     /**
@@ -107,3 +182,12 @@
             .verify();
     }
+
+    private static double getOriginalLength(Collection<Way> ways) {
+        double len = 0;
+        for (Way w : ways) {
+            len += w.getLength();
+        }
+        return len;
+    }
+
 }
