使用 CatmullRom 生成平滑曲线

This commit is contained in:
2025-11-26 00:23:55 +08:00
parent ac86ab3976
commit 0d15c60606
3 changed files with 141 additions and 3 deletions

View File

@@ -61,6 +61,9 @@ dependencies {
implementation(project(":orx-palette")) {
exclude(group = "org.openrndr", module = "openrndr-draw")
}
implementation(project(":orx-shapes")) {
exclude(group = "org.openrndr", module = "openrndr-draw")
}
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)

View File

@@ -9,6 +9,8 @@ import com.icegps.orx.ktx.area
import com.icegps.orx.ktx.toColorInt
import com.icegps.orx.ktx.toMapboxPoint
import com.icegps.orx.ktx.toast
import com.icegps.orx.triangulation.DelaunayTriangulation3D
import com.icegps.orx.triangulation.Triangle3D
import com.icegps.shared.ktx.TAG
import com.mapbox.geojson.Feature
import com.mapbox.geojson.FeatureCollection
@@ -30,8 +32,7 @@ import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import com.icegps.orx.triangulation.DelaunayTriangulation3D
import com.icegps.orx.triangulation.Triangle3D
import org.openrndr.extra.shapes.splines.CatmullRomChain2
import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
import org.openrndr.shape.Rectangle
@@ -294,10 +295,21 @@ class ContoursManager(
style.addLayer(layer)
}
private var useCatmullRom: Boolean = true
fun setCatmullRom(enabled: Boolean) {
useCatmullRom = enabled
}
fun contoursToLineFeatures(contours: List<ShapeContour>, color: Int): List<List<Feature>> {
return contours.drop(1).map { contour ->
contour.segments.map { segment ->
LineString.fromLngLats(listOf(segment.start.toMapboxPoint(), segment.end.toMapboxPoint()))
LineString.fromLngLats(
listOf(
segment.start.toMapboxPoint(),
segment.end.toMapboxPoint()
)
)
}.map { lineString ->
Feature.fromGeometry(lineString).apply {
// 将颜色Int转换为十六进制字符串
@@ -311,6 +323,12 @@ class ContoursManager(
val lists = contours.drop(0).filter { it.segments.isNotEmpty() }.map { contour ->
val start = contour.segments[0].start
listOf(start) + contour.segments.map { it.end }
}.map {
if (!useCatmullRom) return@map it
val cmr = CatmullRomChain2(it, 1.0, loop = true)
val contour = ShapeContour.fromPoints(cmr.positions(200), true)
val start = contour.segments[0].start
listOf(start) + contour.segments.map { it.end }
}.map { points -> points.map { it.toMapboxPoint() } }
if (lists.isEmpty()) {

View File

@@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<com.mapbox.maps.MapView
android:id="@+id/map_view"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="3" />
<ScrollView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.slider.Slider
android:id="@+id/slider_target_height"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:value="0"
android:valueFrom="0"
android:valueTo="100" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="栅格大小:" />
<com.google.android.material.slider.Slider
android:id="@+id/cell_size"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:value="1"
android:valueFrom="1"
android:valueTo="100" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="高度范围:" />
<com.google.android.material.slider.RangeSlider
android:id="@+id/height_range"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:valueFrom="0"
android:valueTo="100" />
</LinearLayout>
<Switch
android:id="@+id/switch_grid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:switchPadding="16dp"
android:text="栅格网" />
<Switch
android:id="@+id/switch_triangle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:switchPadding="16dp"
android:text="三角网" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="坐标数量:" />
<TextView
android:id="@+id/point_count"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<Button
android:id="@+id/update"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="刷新界面" />
<Button
android:id="@+id/clear_points"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="清除所有点" />
</LinearLayout>
</ScrollView>
</LinearLayout>