เอกสารประกอบ / Core / การฉายภาพและการซูม

การฉายภาพและการซูม

การฉายภาพ คือการนำโลกทรงกลมมาลงบนหน้าจอแบน และการซูม บ่งบอกถึงระดับการซูมแค่ไหน แม้ว่าคำจำกัดความของทั้งสองอย่างจะแตกต่างกันไปตามผู้ให้บริการ แต่ MapConductor ใช้ค่าคงที่และสูตรเดียวกันบน 3 แพลตฟอร์ม และจัดรูปแบบค่าที่เปิดเผยให้เป็นมาตราส่วนเดียวกัน วิธีการใช้กล้องดูได้ที่หน้ากล้อง ส่วนที่นี่จะพูดถึงค่าตัวเลขที่อยู่ภายใต้นั้น

ELLIPSOID
WGS84
PROJECTIONS
WebMercator · WGS84
ZOOM RANGE
0 – 22
แพลตฟอร์ม

01 · ค่าคงที่ของโลก

การฉายภาพ การคำนวณทางภูมิศาสตร์ และการคำนวณกระเบื้อง ล้วนอ้างอิงค่าคงที่ของ Earth

ค่าคงที่
ค่า
คำอธิบาย
RADIUS_METERS
6 378 137.0
กึ่งแกนเอกของ WGS84 (รัศมีเส้นศูนย์สูตร)
CIRCUMFERENCE_METERS
2πa
เส้นรอบรูปเส้นศูนย์สูตรทั้งหมด ใช้สำหรับการคำนวณความละเอียดของกระเบื้อง
FLATTENING
1 / 298.257223563
แบน ใช้ในการคำนวณเส้นทางเฉพาะทางภูมิศาสตร์ของโมเดลทรงรี
SEMI_MINOR_AXIS_METERS
a(1 − f)
กึ่งแกนโท (รัศมีขั้วโลก)
ECCENTRICITY_SQUARED
f(2 − f)
กำลังสองของเอ็กซ์เซนทริกซิตี้อันดับแรก
WEB_MERCATOR_MAX_EXTENT_METERS
πa ≈ 20 037 508.34
ค่าสูงสุดที่เป็นไปได้สำหรับพิกัด Web Mercator พิกัด x และ y หลังการฉายภาพจะอยู่ในช่วงนี้

02 · การฉายภาพ

ประเภทของการฉายภาพมีเพียง `project` และ `unproject` เท่านั้น เป็นการดำเนินการสมมาตรที่ฉายพิกัดลงในพิกัดระนาบ (`Offset`) และส่งกลับคืน มีการนำไปใช้จริง 2 แบบ

WebMercator

Web Mercator ในหน่วยเมตร

ฉายลงบนระนาบ ±20,037,508.34 m เหมือนกับ EPSG:3857 ใช้สำหรับการคำนวณขอบเขตของไทล์และการแปลงระยะทางบนหน้าจอเป็นเมตร

WGS84

พิกัดไทล์ 256 พิกเซล

ฉายลงในระบบพิกัดที่ใช้ไทล์เดียวที่ซูม 0 (256×256) เป็นหน่วย เป็นระบบพิกัดที่เรนเดอร์ใช้สร้างภาพไทล์

com.mapconductor.core.projection
interface ProjectionInterface {
    fun project(position: GeoPointInterface): Offset
    fun unproject(point: Offset): GeoPointInterface
}

val meters = WebMercator.project(tokyo)   // x, y เป็นเมตร
val tile = WGS84.project(tokyo)           // พิกัดไทล์ 0 ถึง 256

เมื่อต้องการแปลงพิกเซลบนหน้าจอและพิกัดร่วมกัน โปรดใช้ `toScreenOffset` / `fromScreenOffset` ของ `MapViewHolder` แทนการฉายภาพ จะสะท้อนความเอียงและการหมุนจริงของกล้องที่แสดงอยู่

03 · การแปลงระหว่างการซูมและระดับความสูง

ผู้ให้บริการระบบกระเบื้อง 2D ใช้ระดับการซูม ส่วนระบบ 3D ใช้ระดับความสูงของกล้องหรือระยะการมองเห็นเพื่อแสดงสเกล MapConductor แปลงทั้งสองนี้ระหว่างกัน และแสดงให้แอปเห็นในสเกลการซูมเดียวกันเสมอ การแปลงถูกนำไปใช้สำหรับแต่ละผู้ให้บริการในรูปแบบคลาสหนึ่งที่สืบทอดจากคลาสนามธรรมทั่วไป

การแปลงรวมถึงละติจูดและความเอียง เนื่องจาก Web Mercator ขยายแผนที่มากขึ้นในละติจูดสูง ดังนั้นแม้ว่าจะซูมเท่ากัน ระดับความสูงของกล้องที่จำเป็นที่เส้นศูนย์สูตรและในละติจูดสูงจะแตกต่างกันหลายเท่า

รูปที่ · ระดับความสูงของกล้องที่จำเป็นเมื่อค่าซูมเท่ากัน (อัตราส่วนที่เส้นศูนย์สูตรเท่ากับ 1)
0° · เส้นศูนย์สูตร
×1.00
30° · ไคโร
×0.87
35° · โตเกียว
×0.82
แม้ว่าจะเป็น `zoom` 14 เหมือนกัน คุณกำลังดูจากตำแหน่งที่ต่ำกว่าเส้นศูนย์สูตรประมาณ 20%
60° · ออสโล
×0.50
70° · ทรอมเซอ
×0.34
ความแตกต่างจากเส้นศูนย์สูตรประมาณ 3 เท่า หากปรับแต่งเฉพาะระดับความสูงและไม่สนใจละติจูด ช่วงที่มองเห็นจะเลื่อนไปถึงระดับนี้
AbstractZoomAltitudeConverter · Kotlin
abstract class AbstractZoomAltitudeConverter(
    protected val zoom0Altitude: Double,
) {
    abstract fun zoomLevelToAltitude(zoomLevel: Double, latitude: Double, tilt: Double): Double

    abstract fun altitudeToZoomLevel(altitude: Double, latitude: Double, tilt: Double): Double
}

แต่ละแพ็กเกจของผู้ให้บริการมีตัวแปลง (`ZoomAltitudeConverter`) แอปไม่จำเป็นต้องเรียกโดยตรง แต่สามารถใช้ได้เมื่อสร้างการแสดงผล 3D ของคุณเอง

ดูการนำไปใช้งานในวิดีโอ · Android + MapLibreKotlin · Jetpack Compose
// The same camera position handed to both states
val shared = MapCameraPosition(
    position = GeoPoint.fromLatLong(35.6812, 139.7671),
    zoom = 14.0,
)
val maplibre = rememberMapLibreMapViewState(cameraPosition = shared)
val googlemaps = rememberGoogleMapViewState(cameraPosition = shared)

// Move one and the same value goes to the other
Row {
    MapLibreMapView(
        state = maplibre,
        modifier = Modifier.weight(1f),
        onCameraMoveEnd = { googlemaps.moveCameraTo(it) },
    )
    GoogleMapView(
        state = googlemaps,
        modifier = Modifier.weight(1f),
        onCameraMoveEnd = { maplibre.moveCameraTo(it) },
    )
}
วิดีโอตัวอย่าง · เปรียบเทียบค่าซูมเดียวกันระหว่างผู้ให้บริการ
ยังไม่ได้ถ่ายวิดีโอสลับผู้ให้บริการโดยคง `zoom` ไว้เหมือนเดิม และแสดงว่าสเกลจริงคลาดเคลื่อนไปเพียงใด

04 · ค่าขีดจำกัด

ค่าคงที่ที่ใช้สำหรับการแปลง เพื่อป้องกันสูตรไม่เป็นอนันต์ใกล้ขั้วหรือมุมมองจากด้านบน จึงกำหนดค่าต่ำสุดของ `cos` ไว้เป็นค่าคงที่

DEFAULT_ZOOM0_ALTITUDE
171,319,879 m
ZOOM_FACTOR
2.0
MIN / MAX_ZOOM_LEVEL
0.0 / 22.0
MIN / MAX_ALTITUDE
100 / 50,000,000 m
MIN_COS_LAT
0.01
MIN_COS_TILT
0.05
WEB_MERCATOR_INITIAL_MPP_256
156,543.033928
TILE SIZE
256 px

ระดับความสูงอ้างอิงที่ `zoom` 0 ไม่ใช่ค่าที่ตั้งขึ้นจากทฤษฎีเพียงอย่างเดียว เป็นผลจากการสอบเทียบโดยวัดช่วงที่มองเห็นจริงในแต่ละเอ็นจิ้นเมื่อระบุซูมเดียวกัน เพื่อให้พื้นที่ตรงกัน ค่าคงที่เพียงอย่างเดียวคือความสัมพันธ์ที่ว่าระดับความสูงจะลดลงครึ่งหนึ่งต่อขั้นซูม (`ZOOM_FACTOR = 2`) และค่าอ้างอิงนี้

หน้าที่เกี่ยวข้อง