Index: src/uk/me/parabola/mkgmap/CommandArgsReader.java
===================================================================
--- src/uk/me/parabola/mkgmap/CommandArgsReader.java	(revision 4392)
+++ src/uk/me/parabola/mkgmap/CommandArgsReader.java	(working copy)
@@ -63,6 +63,7 @@
 		add(new CommandOption("overview-mapnumber", "63240000"));
 		add(new CommandOption("poi-address", ""));
 		add(new CommandOption("merge-lines", ""));
+		add(new CommandOption("is-in-landuse", "residential"));
 	}
 
 	/**
Index: src/uk/me/parabola/mkgmap/reader/osm/LanduseHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/LanduseHook.java	(nonexistent)
+++ src/uk/me/parabola/mkgmap/reader/osm/LanduseHook.java	(working copy)
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2017.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 3 or
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ */
+
+package uk.me.parabola.mkgmap.reader.osm;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.log.Logger;
+import uk.me.parabola.mkgmap.osmstyle.NameFinder;
+import uk.me.parabola.mkgmap.reader.osm.boundary.Boundary;
+import uk.me.parabola.mkgmap.reader.osm.boundary.BoundaryQuadTree;
+import uk.me.parabola.util.EnhancedProperties;
+import uk.me.parabola.util.Java2DConverter;
+
+/**
+ * Hook to add information about given landuse areas to an element. If the element lies within the given area xxx
+ * a tag mkgmap:lu:xxx is added. Example:
+ * tag mkgmap:lu:cemetery is added to elements that lie within a landuse=cemetery area.
+ * Special case: Legacy support for old ResidentialHook
+ * If style uses mkgmap:residential instead of mkgmap:lu:residential we add this tag.
+ * 
+ * @author Gerd Petermann
+ *
+ */
+public class LanduseHook implements OsmReadingHooks {
+	private static final Logger log = Logger.getLogger(LanduseHook.class);
+
+	private static final String LANDUSE_PREFIX = "mkgmap:lu:";
+	private Map<String, BoundaryQuadTree> landuseTreeMap = new LinkedHashMap<>();
+	private String[] wantedTrees;
+	private boolean legacyStyle;
+	private ElementSaver saver;
+	private NameFinder nameFinder;
+
+	@Override
+	public boolean init(ElementSaver saver, EnhancedProperties props) {
+		String opt = props.getProperty("is-in-landuse");
+		if (!props.getProperty("residential-hook", true)) {
+			System.err.println("Found undocumented option residential-hook=false, is now ignored, please see option --is-in-landuse");
+		}
+		wantedTrees = getCommaSeparatedTrimmedList(opt);
+		if (wantedTrees.length == 0) 
+			return false; // hook is disabled
+		
+		legacyStyle = props.getProperty(OsmMapDataSource.ADD_MKGMAP_RESIDENTIAL, false);
+		this.nameFinder = new NameFinder(props);
+		this.saver = saver;
+		return true;
+	}
+	
+	/**
+	 * Compute list of values from a comma separated list, remove enclosing hyphens and blanks
+	 * @param s the string to parse
+	 * @return array of strings, length = 0 if s is null or empty
+	 */
+	private static String[] getCommaSeparatedTrimmedList(String s) {
+		String[] list = {};
+		if (s != null) {
+			if (s.startsWith("'") || s.startsWith("\""))
+				s = s.substring(1);
+			if (s.endsWith("'") || s.endsWith("\""))
+				s = s.substring(0, s.length() - 1);
+			list = s.split(",");
+			for (int i = 0; i < list.length; i++) {
+				list[i] = list[i].trim();
+			}
+		}
+		return list;
+	}
+
+
+	@Override
+	public void end() {
+		log.info("Starting with landuse hook");
+		long t1 = System.currentTimeMillis();
+		for (String landuse: wantedTrees) {
+			landuseTreeMap.put(landuse, buildInsideBoundaryTree(landuseTagKey, landuse));
+		}
+		long t2 = System.currentTimeMillis();
+		log.info("Creating landuse bounds took", (t2 - t1), "ms");
+		
+		// process all nodes that might be converted to a garmin node (tag count > 0)
+		for (Node node : saver.getNodes().values()) {
+			if (node.getTagCount() > 0 && saver.getBoundingBox().contains(node.getLocation())) {
+				processElem(node);
+			}
+		}
+
+		// process  all ways that might be converted to a garmin way (tag count > 0)
+		for (Way way : saver.getWays().values()) {
+			if (way.getTagCount() > 0) {
+				processElem(way);
+			}
+		}
+		long t3 = System.currentTimeMillis();
+		log.info("Using landuse hook took", (t3 - t2), "ms");
+		// free memory
+		landuseTreeMap.clear();
+	}
+
+	private static final short landuseTagKey = TagDict.getInstance().xlate("landuse"); 
+	private static final short nameTagKey = TagDict.getInstance().xlate("name");  
+	private static final short styleFilterTagKey = TagDict.getInstance().xlate("mkgmap:stylefilter");
+	private static final short otherKey = TagDict.getInstance().xlate("mkgmap:other");
+	
+	private BoundaryQuadTree buildInsideBoundaryTree(short tagKey, String val) {
+		List<Boundary> rings = new ArrayList<>();
+		Tags tags = new Tags();
+
+		for (Way way : saver.getWays().values()) {
+			if (way.hasIdenticalEndPoints() && val.equals(way.getTag(tagKey))) {
+				if ("polyline".equals(way.getTag(styleFilterTagKey)))
+					continue;
+				String name = nameFinder.getName(way);
+				tags.put(nameTagKey, name == null ? "yes" : name);
+				Boundary b = new Boundary(Java2DConverter.createArea(way.getPoints()), tags, "w" + way.getId());
+				rings.add(b);
+			}
+		}
+		log.info("adding ", rings.size(), "areas for", val, "to spatial index");
+		return new BoundaryQuadTree(saver.getBoundingBox(), rings, null);
+	}
+
+	/**
+	 * Extract the location info and perform a test 
+	 * against the BoundaryQuadTree. If found, assign the tag.
+	 * @param elem A way or Node
+	 */
+	private void processElem(Element elem) {
+		for (Entry<String, BoundaryQuadTree> entry : landuseTreeMap.entrySet()) {
+			BoundaryQuadTree tree = entry.getValue();
+			String tagVal = entry.getKey();
+			Tags isinTags = null;
+			if (elem instanceof Node) {
+				Node node = (Node) elem;
+				isinTags = tree.get(node.getLocation());
+			} else if (elem instanceof Way) {
+				Way way = (Way) elem;
+				// try the mid point of the way first
+				int middle = way.getPoints().size() / 2;
+				Coord loc = way.hasIdenticalEndPoints() ? way.getCofG() : way.getPoints().get(middle);
+				if (!tagVal.equals(way.getTag(landuseTagKey)))
+					isinTags = tree.get(loc);
+			}
+
+			if (isinTags != null) {
+				String prefix = LANDUSE_PREFIX;
+				if (legacyStyle && "residential".equals(tagVal)) {
+					prefix = "mkgmap:";
+				}
+				elem.addTag(prefix + tagVal, isinTags.get(otherKey));
+			}
+		}
+	}
+	
+	@Override
+	public Set<String> getUsedTags() {
+		Set<String> used = new HashSet<>();
+		used.add("landuse");
+		used.add("name");
+		return used;
+	}
+}
Index: src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java	(revision 4392)
+++ src/uk/me/parabola/mkgmap/reader/osm/OsmMapDataSource.java	(working copy)
@@ -72,7 +72,7 @@
 			new HighwayHooks(),
 			new LocationHook(),
 			new POIGeneratorHook(),
-			new ResidentialHook(),
+			new LanduseHook(),
 			new HousenumberHooks(),
 	};
 	protected OsmConverter converter;
@@ -82,6 +82,8 @@
 	private static final LocalDateTime now = LocalDateTime.now();
 	
 	protected static final List<OsmHandler> handlers;
+
+	public static final String ADD_MKGMAP_RESIDENTIAL = "style-uses-mkgmap:residential";
 	static {
 		handlers = new ArrayList<>();
 		handlers.add(new OsmBinHandler());
@@ -334,6 +336,10 @@
 		EnhancedProperties props = getConfig();
 		setStyle(StyleImpl.readStyle(props));
 
+		if (style.getUsedTags().contains("mkgmap:residential")) {
+			System.err.println("Found mkgmap:residential in style, please replace by mkgmap:lu:residential");
+			props.put(ADD_MKGMAP_RESIDENTIAL, "yes");
+		}
 		usedTags.addAll(style.getUsedTags());
 		usedTags.addAll(NameFinder.getNameTags(props));
 		converter = new StyledConverter(style, mapper, props);
Index: src/uk/me/parabola/mkgmap/reader/osm/ResidentialHook.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/ResidentialHook.java	(revision 4392)
+++ src/uk/me/parabola/mkgmap/reader/osm/ResidentialHook.java	(nonexistent)
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2017.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 3 or
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- */
-
-package uk.me.parabola.mkgmap.reader.osm;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
-import uk.me.parabola.imgfmt.app.Coord;
-import uk.me.parabola.log.Logger;
-import uk.me.parabola.mkgmap.osmstyle.NameFinder;
-import uk.me.parabola.mkgmap.reader.osm.boundary.Boundary;
-import uk.me.parabola.mkgmap.reader.osm.boundary.BoundaryQuadTree;
-import uk.me.parabola.util.EnhancedProperties;
-import uk.me.parabola.util.Java2DConverter;
-
-/**
- * Hook to add tag mkgmap:residential to elements that lie within a landuse=residential area.
- * @author Gerd Petermann
- *
- */
-public class ResidentialHook implements OsmReadingHooks {
-	private static final Logger log = Logger.getLogger(ResidentialHook.class);
-
-	
-	private BoundaryQuadTree residentialBoundaries;
-	
-	private ElementSaver saver;
-	private NameFinder nameFinder;
-
-	@Override
-	public boolean init(ElementSaver saver, EnhancedProperties props) {
-		if (!props.getProperty("residential-hook", true))
-			return false; 
-		this.nameFinder = new NameFinder(props);
-		this.saver = saver;
-		return true;
-	}
-
-	@Override
-	public void end() {
-		log.info("Starting with residential hook");
-
-		long t1 = System.currentTimeMillis();
-		residentialBoundaries = buildResidentialBoundaryTree();
-		long t2 = System.currentTimeMillis();
-		log.info("Creating residential bounds took", (t2 - t1), "ms");
-		
-		// process all nodes that might be converted to a garmin node (tagcount > 0)
-		for (Node node : saver.getNodes().values()) {
-			if (node.getTagCount() > 0 && saver.getBoundingBox().contains(node.getLocation())) {
-				processElem(node);
-			}
-		}
-
-		// process  all ways that might be converted to a garmin way (tagcount > 0)
-		for (Way way : saver.getWays().values()) {
-			if (way.getTagCount() > 0) {
-				processElem(way);
-			}
-		}
-		long t3 = System.currentTimeMillis();
-		log.info("Using residential bounds took", (t3 - t2), "ms");
-		// free memory
-		residentialBoundaries = null;
-	}
-
-	private static final short landuseTagKey = TagDict.getInstance().xlate("landuse"); 
-	private static final short nameTagKey = TagDict.getInstance().xlate("name");  
-	private static final short styleFilterTagKey = TagDict.getInstance().xlate("mkgmap:stylefilter");
-	private static final short otherKey = TagDict.getInstance().xlate("mkgmap:other");
-	
-	private BoundaryQuadTree buildResidentialBoundaryTree() {
-		List<Boundary> residentials = new ArrayList<>();
-		Tags tags = new Tags();
-		
-		for (Way way : saver.getWays().values()) {
-			if (way.hasIdenticalEndPoints() && "residential".equals(way.getTag(landuseTagKey))) {
-				if ("polyline".equals(way.getTag(styleFilterTagKey)))
-					continue;
-				String name = nameFinder.getName(way);
-				tags.put(nameTagKey, name == null ? "yes": name);
-				Boundary b = new Boundary(Java2DConverter.createArea(way.getPoints()), tags, "w"+way.getId());
-				residentials.add(b);
-			}
-		}
-		
-		return new BoundaryQuadTree(saver.getBoundingBox(), residentials, null);
-	}
-
-	/**
-	 * Extract the location info and perform a test 
-	 * against the BoundaryQuadTree. If found, assign the tag.
-	 * @param elem A way or Node
-	 */
-	private void processElem(Element elem){
-		Tags residentialTags = null;
-
-		if (elem instanceof Node){
-			Node node = (Node) elem;
-			residentialTags = residentialBoundaries.get(node.getLocation());
-		} else if (elem instanceof Way){
-			Way way = (Way) elem;
-			// try the mid point of the way first
-			int middle = way.getPoints().size() / 2;
-			Coord loc = way.hasIdenticalEndPoints() ? way.getCofG() : way.getPoints().get(middle);
-			if (! "residential".equals(way.getTag(landuseTagKey)))
-				residentialTags = residentialBoundaries.get(loc);
-		}
-
-		if (residentialTags != null) {
-			elem.addTag("mkgmap:residential", residentialTags.get(otherKey));
-		}
-	}
-	
-	@Override
-	public Set<String> getUsedTags() {
-		Set<String> used = new HashSet<>();
-		used.add("landuse");
-		used.add("name");
-		return used;
-	}
-}
-
-
Index: resources/help/en/options
===================================================================
--- resources/help/en/options	(revision 4392)
+++ resources/help/en/options	(working copy)
@@ -687,6 +687,21 @@
 	It is possible to define wildcards for tag values like entrance=*.
 	Default: entrance=main;entrance=yes;building=entrance
 
+--is-in-landuse=value[,value...]
+	Tells mkgmap to calculate a tag for each given landuse area. 
+	Allows to identify eg. buildings within a landuse=residential or ways 
+	within a landuse=cemetery. If an element is within the given landuse area,
+	the information is stored in special tags with prefix mkmap:lu:.
+	Example: If you specify --is-in-landuse=cemetery and an element is within a 
+	landuse=cemetery polygon mkgmap adds the tag
+	mkgmap:lu:cemetery=x where x is either "yes" or the name of the cemetery.
+	The program builds a spatial index for each listed landuse value to be able to compute
+	this information before the style rules in lines and points are applied.
+	The default for this option is residential. To disable the processing use
+	--no-is-in-landuse or an empty list of values.
+	If the style uses the tag mkgmap:residential which was set by earlier versions
+	of mkgmap a warning is printed and the old tag is generated.
+
 --precomp-sea=directory|zipfile
 	Defines the directory or a zip file that contains precompiled sea tiles. 
 	Sea files in a zip file must be located in the zip file's root directory or in 
