//static int livingsign = 0; /// <summary> /// bildet rekursiv den Subdiv-Baum /// </summary> /// <param name="orgmap"></param> /// <param name="parentmap"></param> /// <param name="coordbits"></param> /// <param name="pointtypes"></param> /// <param name="linetypes"></param> /// <param name="areatypes"></param> /// <param name="level"></param> static void buildSubdivmapTree(DetailMap orgmap, DetailMap parentmap, int[] coordbits, IList <SortedSet <int> > pointtypes, IList <SortedSet <int> > linetypes, IList <SortedSet <int> > areatypes, int level = 0) { if (level >= coordbits.Length) { return; } split2Subdivmaps4Bits(orgmap, parentmap, coordbits[level], pointtypes[level], linetypes[level], areatypes[level]); //Console.Write("."); //if (++livingsign % 100 == 0) // Console.Write(livingsign); level++; for (int i = 0; i < parentmap.ChildMapCount; i++) { buildSubdivmapTree(orgmap, parentmap.GetChildMap(i), coordbits, pointtypes, linetypes, areatypes, level); } }
// from MKGMAP: /** * Split the area into portions that have the maximum size. There is a maximum limit to the size of a subdivision (16 bits or about 1.4 degrees at the most detailed zoom level). * * The size depends on the shift level. * * We are choosing a limit smaller than the real max to allow for uncertainty about what happens with features that extend beyond the box. * * If the area is already small enough then it will be returned unchanged. * * @param mapArea The area that needs to be split down. * @return An array of map areas. Each will be below the max size. * * * Die halbe Breite und Höhe einer Subdiv wird jeweils in 16 Bit gespeichert. MKGMAP verwendet sicherheitshalber sogar nur 15 Bit (0x7FFF). Die damit erreichbare * max. Breite und Höhe ist zusätzlich abhängig von der Bitanzahl für die Koordinaten * (SymbolicScaleAndBitsLevel.Bits(level) -> SubdivInfoBasic.Degree(rawunits, coordbits) -> GarminCoordinate.RawUnits2Degree(rawunits, coordbits)). * Schon daraus folgt, dass ein großes Subdiv bei einem größeren Maßstab/Zoom vermutlich in mehrere Subdiv's aufgeteilt werden muss. * * Weiterhin soll die Anzahl der Objekte in einer Subdiv nicht zu groß werden. * MKGMAP: Wenn * Punktanzahl > MAX_NUM_POINTS (0xFF) || * Linienanzahl > MAX_NUM_LINES (0xFF) || * (die Summe der geschätzten Datenbereichsgrößen für Punkte, Linien und Flächen) > MAX_RGN_SIZE (0xFFF8) || * (geschätzten Datenbereichsgrößen für erw. Punkte) > MAX_XT_POINTS_SIZE (0xFF00) || * (geschätzten Datenbereichsgrößen für erw. Linien) > MAX_XT_LINES_SIZE (0xFF00) || * (geschätzten Datenbereichsgrößen für erw. Flächen) > MAX_XT_SHAPES_SIZE (0xFF00) || * Subdiv > WANTED_MAX_AREA_SIZE (0x3FFF) * dann wir die Subdiv geteilt. Dabei wird je nach dem, welcher Wert größer ist, die Breite oder Höhe halbiert. * Linien und Flächen verteiltt MKGMAP nach der Lage ihrer Mittelpunkte. * * -> alle Objekte einer Karte für den akt. Maßstab codieren * Karte (mit den Objekten) rekursiv in Teilkarten aufteilen, wenn * die Breite und/oder Höhe zu groß ist || * Punktanzahl > MAX_NUM_POINTS (0xFF) || * Linienanzahl > MAX_NUM_LINES (0xFF) || * (die Summe der Datenbereichsgrößen für Punkte, Linien und Flächen) > MAX_RGN_SIZE (0xFFF8) || * (Datenbereichsgrößen für erw. Punkte) > MAX_XT_POINTS_SIZE (0xFF00) || * (Datenbereichsgrößen für erw. Linien) > MAX_XT_LINES_SIZE (0xFF00) || * (Datenbereichsgrößen für erw. Flächen) > MAX_XT_SHAPES_SIZE (0xFF00) || * Subdiv > WANTED_MAX_AREA_SIZE (0x3FFF) * * */ /// <summary> /// liefert die Liste der 'obersten' <see cref="DetailMap"/>'s, die jeweils mit den untergeordneten <see cref="DetailMap"/> verbunden sind und jeweils eine Subdiv repräsentieren /// </summary> /// <param name="orgmap"></param> /// <param name="coordbits">Bitanzahl je Ebene</param> /// <param name="pointtypes">erlaubte Punkttypen je Ebene</param> /// <param name="linetypes">erlaubte Linientypen je Ebene</param> /// <param name="areatypes">erlaubte Flächentypen je Ebene</param> /// <returns></returns> public static List <DetailMap> BuildSubdivmapMapTree(DetailMap orgmap, int[] coordbits, IList <SortedSet <int> > pointtypes, IList <SortedSet <int> > linetypes, IList <SortedSet <int> > areatypes) { //Console.WriteLine("Subdiv-Baum erzeugen ..."); //livingsign = 0; DetailMap firstlevelmap = orgmap.Copy(); buildSubdivmapTree(orgmap, firstlevelmap, coordbits, pointtypes, linetypes, areatypes); // Die Childs der firstlevelmap bilden die Subdivs der obersten Ebene. List <DetailMap> result = new List <DetailMap>(); for (int i = 0; i < firstlevelmap.ChildMapCount; i++) { DetailMap sd = firstlevelmap.GetChildMap(i); sd.ParentMap = null; result.Add(sd); } //Console.WriteLine(); return(result); }
/// <summary> /// erzeugt die Subdiv-Maps mit der gewünschten Bitanzahl mit den Objekten aus der Originalkarte im gewünschten Bereich und verknüpft sie mit der übergeordneten Map /// </summary> /// <param name="orgmap">Originalkarte mit ALLEN Objekten und max. Auflösung</param> /// <param name="parentmap"></param> /// <param name="coordbits">Bitanzahl</param> /// <param name="pointtypes">erlaubte Punkttypen</param> /// <param name="linetypes">erlaubte Linientypen</param> /// <param name="areatypes">erlaubte Flächentypen</param> static void split2Subdivmaps4Bits(DetailMap orgmap, DetailMap parentmap, int coordbits, SortedSet <int> pointtypes, SortedSet <int> linetypes, SortedSet <int> areatypes) { coordbits = Math.Max(10, Math.Min(coordbits, 24)); // eingrenzen 10 .. 24 DetailMap map4bits = PrepareMap(orgmap, coordbits, parentmap.DesiredBounds, pointtypes, linetypes, areatypes); List <DetailMap> subdivmaps = splitDetailMap(map4bits, coordbits, 0, 0); if (subdivmaps == null) { subdivmaps = new List <DetailMap>() { map4bits } } ; while (parentmap.ChildMapCount > 0) // ev. vorhandene Childs lösen { parentmap.GetChildMap(0).ParentMap = null; } foreach (var item in subdivmaps) { item.ParentMap = parentmap; } } // größere Werte können Probleme bei der Codierung der Delta-Werte ergeben //const int MAX_BOUND4LINE = 0x7FFF; // MKGMAP; etwa 0.703° bei 24 Bit //const int MAX_BOUND4AREA = 0xFFFF; // MKGMAP; etwa 1.406° bei 24 Bit const int MAX_BOUND4LINE = 0x7FFF; const int MAX_BOUND4AREA = 0x3FFF; /// <summary> /// kleinste Maximalgröße /// </summary> const int MIN_4MAX_BOUND = 0x7FFF; // MKGMAP 0x8000