<template>
	<div class="main-content">
		<div class="main-content-title">
			<span>空间分析</span>
			<el-icon size="16" color="#fff" @click="closeDiv"><Close /></el-icon>
		</div>
		<div class="main-content-menu" v-if="mainMenuShow">
			<div v-for="(item, i) in menuList" :key="i" class="menu-item" @click="mapOperate(item.name)">
				<div><img class="icon" :src="item.icon" alt="" srcset="" /></div>
				<div>{{ item.name }}</div>
			</div>
		</div>
		<div class="operate-content" v-if="subMenuShow">
			<!-- 日照分析 -->
			<div class="sunshine" v-if="selectedName == '日照分析'">
				<div class="title">
					<el-icon class="back" size="14" @click="backMainMenu"><ArrowLeft /></el-icon>
					<span>日照分析</span>
					<!-- <el-icon class="delete" size="14"><Delete /></el-icon> -->
				</div>
				<div class="subtitle-tip">提示:模拟设定时间范围内的太阳光照效果。</div>
				<div class="item-classify">
					<div class="item-classify-item">
						<span>日期选择：</span>
						<el-date-picker v-model="allProperty.currDate" type="date" format="YYYY-MM-DD" value-format="YYYY-MM-DD" />
					</div>
					<div class="item-classify-item">
						<span>时间选择：</span>
						<el-slider v-model="allProperty.timeVal" :min="0" :max="1440" :step="1" @input="timeChange" />
					</div>
					<div class="item-classify-item">
						<span>当前时间：</span>
						<span>{{ allProperty.currDate }} {{ hours }} 时 {{ minutes }}分</span>
					</div>
				</div>
				<div class="sunshing-play">
					<el-button type="primary" @click="playOrPause">{{ sunshineText }}</el-button>
				</div>
			</div>
			<!-- 可视域分析 -->
			<div class="viewShed" v-if="selectedName == '可视域'">
				<div class="title">
					<el-icon class="back" size="14" @click="backMainMenu"><ArrowLeft /></el-icon>
					<span>可视域分析</span>
					<el-icon class="delete" size="14" @click="clearShow"><Delete /></el-icon>
				</div>
				<div class="subtitle-tip">提示:单击按钮后在图上绘制，红色代表不可视，绿色代表可视。</div>
				<div class="item-classify">
					<div class="item-classify-item">
						<span>四周方向：</span>
						<el-slider v-model="allProperty.heading" :max="360" @input="e => viewShedOperate(e, 'heading')" />
					</div>
					<div class="item-classify-item">
						<span>视角距离：</span>
						<el-slider v-model="allProperty.distance" :step="10" :max="5000" @input="e => viewShedOperate(e, 'distance')" />
					</div>
					<div class="item-classify-item">
						<span>透明度：</span>
						<el-slider v-model="allProperty.opacity" :step="0.1" :max="1" @input="e => viewShedOperate(e, 'opacity')" />
					</div>
					<div class="item-classify-item">
						<span>视椎线框：</span>
						<el-switch v-model="allProperty.showFrustum" @input="e => viewShedOperate(e, 'showFrustum')" />
					</div>
				</div>
				<div class="sunshing-play">
					<el-button type="primary" @click="addviewShed">添加可视域</el-button>
					<el-button type="primary" @click="saveJson">保存</el-button>
				</div>
			</div>
			<!-- 方量分析 -->
			<div class="volumeAnalysis" v-if="selectedName == '方量分析'">
				<div class="title">
					<el-icon class="back" size="14" @click="backMainMenu"><ArrowLeft /></el-icon>
					<span>方量分析</span>
					<el-icon class="delete" size="14" @click="clearShow"><Delete /></el-icon>
				</div>
				<div class="subtitle-tip">提示:请首先单击 “绘制区域” 按钮，再在图上绘制分析区域。</div>
				<div class="item-classify">
					<div class="item-classify-item">
						<span>基准面高(米)：</span>
						<el-input-number v-model="allProperty.height" controls-position="right" @change="e => volumeOperate(e, 'height')" />
						<el-button v-if="allProperty.height != 0" type="primary" @click="selectHeight">点选高度</el-button>
					</div>
					<div class="item-classify-item">
						<span>围墙底高(米)：</span>
						<el-input-number
							v-model="allProperty.minHeight"
							controls-position="right"
							@change="e => volumeOperate(e, 'minHeight')"
						/>
						<span>（可选）</span>
					</div>
					<div class="item-classify-item">
						<span>围墙顶高(米)：</span>
						<el-input-number
							v-model="allProperty.maxHeight"
							controls-position="right"
							@change="e => volumeOperate(e, 'maxHeight')"
						/>
						<span>（可选）</span>
					</div>
				</div>
				<div class="volume-operate">
					<el-button type="primary" @click="addVolume">绘制区域</el-button>
				</div>
			</div>
			<!-- 地形开挖 -->
			<div class="areaDraw" v-if="selectedName == '地形开挖'">
				<div class="title">
					<el-icon class="back" size="14" @click="backMainMenu"><ArrowLeft /></el-icon>
					<span>地形开挖</span>
					<el-icon class="delete" size="14" @click="clearShow"><Delete /></el-icon>
				</div>
				<div class="subtitle-tip">提示:单击“矩形开挖”或“多边形开挖”按钮开始绘制开挖区域。</div>
				<div class="item-classify">
					<div class="item-classify-item">
						<span>开挖深度：</span>
						<el-input-number
							v-model="allProperty.diffHeight"
							controls-position="right"
							@blur="e => areaOperate(e, 'diffHeight')"
						/>
						<span>（米）</span>
					</div>
				</div>
				<div class="volume-operate">
					<el-button type="primary" @click="btnDrawExtent">添加矩形</el-button>
					<el-button type="primary" @click="btnDraw">添加多边形</el-button>
					<el-button type="primary" @click="saveJson">保存</el-button>
				</div>
			</div>
			<!-- 地表透明 -->
			<div class="surfaceOpacity" v-if="selectedName == '地表透明'">
				<div class="title">
					<el-icon class="back" size="14" @click="backMainMenu"><ArrowLeft /></el-icon>
					<span>地表透明</span>
					<!-- <el-icon class="delete" size="14" @click="clearShow"><Delete /></el-icon> -->
				</div>
				<div class="subtitle-tip">提示:可以透明地表，进入地下模式，可以看地下管网等数据。</div>
				<div class="item-classify">
					<div class="item-classify-item">
						<span>状态：</span>
						<el-checkbox v-model="allProperty.enabled" @change="e => surfaceOpacityOperate(e, 'enabled')"
							>开启地下模式</el-checkbox
						>
					</div>
					<div class="item-classify-item">
						<span>透明度：</span>
						<el-slider v-model="allProperty.alpha" :step="0.1" :max="1" @input="e => surfaceOpacityOperate(e, 'alpha')" />
					</div>
				</div>
			</div>
			<!-- 坡度坡向 -->
			<div class="slopeAspect" v-if="selectedName == '坡度坡向'">
				<div class="title">
					<el-icon class="back" size="14" @click="backMainMenu"><ArrowLeft /></el-icon>
					<span>坡度坡向</span>
					<el-icon class="delete" size="14" @click="clearShow"><Delete /></el-icon>
				</div>
				<div class="subtitle-tip">提示:单击按钮后在图上绘制区域。</div>
				<div class="item-classify">
					<div class="item-classify-item">
						<span>插值数：</span>
						<el-input-number v-model="allProperty.splitNum" controls-position="right" />
					</div>
					<div class="item-classify-item">
						<span>地表渲染：</span>
						<el-radio-group v-model="allProperty.shadingType" @change="e => slopeAspectOperate(e, 'shadingType')">
							<el-radio label="none">无阴影</el-radio>
							<el-radio label="slope">坡度</el-radio>
							<el-radio label="aspect">坡向</el-radio>
						</el-radio-group>
					</div>
				</div>
				<div class="volume-operate">
					<el-button type="primary" @click="btnSlopeAspectDrawExtent">添加矩形</el-button>
					<el-button type="primary" @click="btnSlopeAspectDraw">添加多边形</el-button>
				</div>
			</div>
			<!-- 模型剖切 -->
			<div class="modelSection" v-if="selectedName == '模型剖切'">
				<div class="title">
					<el-icon class="back" size="14" @click="backMainMenu"><ArrowLeft /></el-icon>
					<span>模型剖切</span>
					<el-icon class="delete" size="14" @click="clearShow"><Delete /></el-icon>
				</div>
				<div class="subtitle-tip">提示:先图上点选模型后，设置剖切方向及距离。</div>
				<div class="item-classify">
					<!-- <div class="item-classify-item">
						<span>选择模型：</span>
						<span>未选择</span>
						<el-button type="primary" @click="selectModal">图上选点</el-button>
					</div> -->
					<div class="item-classify-item">
						<span>按线剖切：</span>
						<el-button type="primary" @click="drawSectionLine">绘制线</el-button>
					</div>
					<div class="item-classify-item">
						<span>按面裁剪：</span>
						<el-button type="primary" @click="drawSectionPoly">绘制面</el-button>
						<el-radio-group v-model="allProperty.clipOutSide" @change="e => modelSectionOperate(e, 'clipOutSide')">
							<el-radio :label="false">内裁</el-radio>
							<el-radio :label="true">外裁</el-radio>
						</el-radio-group>
					</div>
					<div class="item-classify-item">
						<span>剖切方向：</span>
						<el-radio-group v-model="allProperty.type" style="width: 70%" @change="e => modelSectionOperate(e, 'type')">
							<el-radio label="ZR">顶</el-radio>
							<el-radio label="Z">底</el-radio>
							<el-radio label="XR">东</el-radio>
							<el-radio label="X">西</el-radio>
							<el-radio label="Y">南</el-radio>
							<el-radio label="YR">北</el-radio>
						</el-radio-group>
					</div>
					<div class="item-classify-item">
						<span>剖切距离：</span>
						<el-input-number
							v-model="allProperty.sectionDistance"
							controls-position="right"
							@change="e => modelSectionOperate(e, 'sectionDistance')"
						/>
					</div>
				</div>
			</div>
			<!-- 模型压平 -->
			<div class="modelFlatten" v-if="selectedName == '模型压平'">
				<div class="title">
					<el-icon class="back" size="14" @click="backMainMenu"><ArrowLeft /></el-icon>
					<span>模型压平</span>
					<el-icon class="delete" size="14" @click="clearShow"><Delete /></el-icon>
				</div>
				<div class="subtitle-tip">
					提示: 1、只支持部分模型压平(如有带着色器的)； 2、部分模型的压平可能存在异常(如缩放出现碎片现象)。
				</div>
				<div class="item-classify">
					<div class="item-classify-item">
						<span>选择模型：</span>
						<el-button type="primary" @click="showDytDemo">大雁塔</el-button>
						<el-button type="primary" @click="showTehDemo">天鹅湖</el-button>
					</div>
					<div class="item-classify-item">
						<span>压平区高度：</span>
						<el-input-number v-model="allProperty.flattenHeight" controls-position="right" @change="modelFlattenOperate" />
					</div>
				</div>
				<div class="volume-operate">
					<el-button type="primary" @click="btnModelFlattenDrawExtent">添加矩形</el-button>
					<el-button type="primary" @click="btnModelFlattenDraw">添加多边形</el-button>
				</div>
			</div>
			<!-- 限高分析 -->
			<div class="heightLimit" v-if="selectedName == '限高分析'">
				<div class="title">
					<el-icon class="back" size="14" @click="backMainMenu"><ArrowLeft /></el-icon>
					<span>限高分析</span>
					<el-icon class="delete" size="14" @click="clearShow"><Delete /></el-icon>
				</div>
				<div class="item-classify">
					<!-- <div class="item-classify-item">
						<span>地表海拔：</span>
                        <span>0米</span>
						<el-button type="primary" @click="drawSectionLine">绘制线</el-button>
					</div> -->
					<div class="item-classify-item">
						<span>限制高度：</span>
						<el-slider v-model="allProperty.limitHeight" :max="1000" @input="limitHeightOperate" />
					</div>
					<div class="item-classify-item">
						<span>当前高度：</span>
						<span>{{ allProperty.limitHeight }}米</span>
					</div>
					<div class="item-classify-item">
						<span>分析区域：</span>
						<el-button type="primary" @click="drawheightLimitDrawExtent">绘制矩形</el-button>
						<el-button type="primary" @click="drawheightLimitPoly">绘制面</el-button>
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

<script lang="ts" setup>
//引入cesium基础库
import "mars3d-cesium/Build/Cesium/Widgets/widgets.css";
import * as Cesium from "mars3d-cesium";
//导入mars3d主库
import "mars3d/dist/mars3d.css";
import * as mars3d from "mars3d";
import dayjs from "dayjs";
import { ref, watch, onMounted, computed, onUnmounted } from "vue";
import { ElMessage } from "element-plus";
const props = defineProps(["mapInstance"]);
const emits = defineEmits(["hiddenConfim", "saveJson"]);
const mainMenuShow = ref(true);
const subMenuShow = ref(false);
const sunshineText = ref("播放");
const allProperty = ref<any>({
	// 日照分析数据
	timeVal: 420,
	currDate: dayjs().format("YYYY-MM-DD"),
	// 可视域数据
	heading: 45,
	distance: 80,
	opacity: 0.8,
	showFrustum: true,
	// 方量分析数据
	height: 0,
	minHeight: 0,
	maxHeight: 0,
	// 地形开挖数据
	diffHeight: 20,
	// 地下透明数据
	enabled: false,
	alpha: 0.5,
	// 坡度坡向数据
	splitNum: 10,
	shadingType: "none",
	// 模型剖切
	clipOutSide: false,
	type: "ZR",
	sectionDistance: 0,
	// 模型压平
	flattenHeight: 0,
	// 限高分析
	limitHeight: 0
});
const selectedName = ref("");
const menuList = ref([
	{ name: "日照分析", icon: new URL("../../../../assets/images/Mars3DIcon/rzfx.png", import.meta.url).href },
	{ name: "可视域", icon: new URL("../../../../assets/images/Mars3DIcon/ksy.png", import.meta.url).href },
	{ name: "方量分析", icon: new URL("../../../../assets/images/Mars3DIcon/flfx.png", import.meta.url).href },
	{ name: "地形开挖", icon: new URL("../../../../assets/images/Mars3DIcon/dxkw.png", import.meta.url).href },
	{ name: "地表透明", icon: new URL("../../../../assets/images/Mars3DIcon/dbtm.png", import.meta.url).href },
	{ name: "坡度坡向", icon: new URL("../../../../assets/images/Mars3DIcon/pdpx.png", import.meta.url).href },
	{ name: "模型剖切", icon: new URL("../../../../assets/images/Mars3DIcon/mxpq.png", import.meta.url).href },
	{ name: "模型压平", icon: new URL("../../../../assets/images/Mars3DIcon/mxyp.png", import.meta.url).href },
	{ name: "限高分析", icon: new URL("../../../../assets/images/Mars3DIcon/xgfx.png", import.meta.url).href }
]);
const clearBool = ref(true);
const initGraphicLength = ref(0);
let map: any = props.mapInstance;
let graphicLayer: any;
let measure: any;
let measureVolume: any;
let shadows: any;
let terrainClip: any;
let underground: any;
let slope: any;
let contourLine: any;
let modelPlanClip: any;
let tilesetLayer: any; // 3dtiles模型；添加模型选择
let limitHeight: any;
const hours = computed(() => Math.floor(allProperty.value.timeVal / 60));
const minutes = computed(() => Math.floor(allProperty.value.timeVal / 60));
onMounted(() => {
	console.log(map, "66666");
	graphicLayer = new mars3d.layer.GraphicLayer();
	map.addLayer(graphicLayer);
	// map.scene.globe.depthTestAgainstTerrain = true; // 不加无法投射到地形上
	initGraphicLength.value = graphicLayer.getGraphics().length;
	// 地形开挖
	terrainClip = new mars3d.thing.TerrainClip({
		diffHeight: allProperty.value.diffHeight, // 井的深度
		image: "@/assets/images/Mars3DImg/textures/poly-stone.jpg",
		imageBottom: "@/assets/images/Mars3DImg/textures/poly-soil.jpg",
		splitNum: 80, // 井边界插值数
		enabled: true
	});
	map.addThing(terrainClip);
	measure = new mars3d.thing.Measure({
		label: {
			color: "#ffffff",
			font_family: "楷体",
			font_size: 20,
			background: false
		}
	});
	map.addThing(measure);
	// 触发事件：开始分析前
	measure.on(mars3d.EventType.start, function (e: any) {
		console.log("开始分析", e);
	});
	// 触发事件：异步分析完成后
	measure.on(mars3d.EventType.end, function (e: any) {
		console.log(e);
	});
	// 渲染效果
	contourLine = new mars3d.thing.ContourLine({
		contourShow: false, // 是否显示等高线
		shadingType: "none", // 地表渲染效果类型:无nono, 高程 elevation, 坡度slope, 坡向aspect
		shadingAlpha: 0.6 /// 地表渲染的透明度
	});
	map.addThing(contourLine);
});
// 保存配置的图上JSON数据
const saveJson = async () => {
	// if (graphicLayer.length == 0) {
	// 	ElMessage("当前没有任何数据，无需保存！");
	// 	return;
	// }
	console.log(map);
	let arr: any = [];
	map.eachThing(item => {
		console.log(item);
		arr.push(item);
	});
	arr = arr.concat(graphicLayer.getGraphics());
	clearBool.value = false;
	emits("saveJson", arr);
};
// 限定高度--绘制面
const drawheightLimitPoly = () => {
	graphicLayer.clear();
	graphicLayer.startDraw({
		type: "polygon",
		style: {
			color: "#ffff00",
			opacity: 0.3,
			clampToGround: true
		},
		success: function (graphic) {
			// 绘制成功后回调
			const positions = graphic.positionsShow;
			limitHeight.positions = positions;

			graphicLayer.clear();
			console.log("绘制坐标为", JSON.stringify(mars3d.LngLatArray.toArray(positions))); // 方便测试拷贝坐标
		}
	});
};
// 限定高度--绘制矩形
const drawheightLimitDrawExtent = () => {
	graphicLayer.clear();
	graphicLayer.startDraw({
		type: "rectangle",
		style: {
			color: "#ffff00",
			opacity: 0.3,
			clampToGround: true
		},
		success: function (graphic: any) {
			// 绘制成功后回调
			const positions = graphic.getOutlinePositions(false);
			limitHeight.positions = positions;

			graphicLayer.clear();
		}
	});
};
// 限定高度数据操作
const limitHeightOperate = (e: any) => {
	limitHeight.height = e;
};
// 模型压平--绘制多边形
const btnModelFlattenDraw = () => {
	graphicLayer.clear();
	graphicLayer.startDraw({
		type: "polygon",
		style: {
			color: "#007be6",
			opacity: 0.5
		},
		success: function (graphic: any) {
			// 绘制成功后回调
			const positions = graphic.positionsShow;
			graphicLayer.clear();

			console.log("绘制坐标为", JSON.stringify(mars3d.LngLatArray.toArray(positions))); // 方便测试拷贝坐标

			tilesetLayer.flat.addArea(positions, { height: allProperty.value.flattenHeight });
		}
	});
};
// 模型压平--绘制矩形
const btnModelFlattenDrawExtent = () => {
	graphicLayer.clear();
	graphicLayer.startDraw({
		type: "rectangle",
		style: {
			color: "#007be6",
			opacity: 0.2,
			outline: false
		},
		success: function (graphic: any) {
			// 绘制成功后回调
			const positions = graphic.getOutlinePositions(false);
			graphicLayer.clear();

			console.log("绘制坐标为", JSON.stringify(mars3d.LngLatArray.toArray(positions))); // 方便测试拷贝坐标

			tilesetLayer.flat.addArea(positions, { height: allProperty.value.flattenHeight });
		}
	});
};
// 模型剖切数据改变
const modelFlattenOperate = (e: any) => {
	tilesetLayer.flat.updateHeight(e);
};
const showTehDemo = () => {
	// 以下数据为cesiumlab v3处理，目前其材质有做偏移处理，不知道内部逻辑及具体值，无法平整压平。
	tilesetLayer = new mars3d.layer.TilesetLayer({
		name: "合肥天鹅湖",
		url: "//data.mars3d.cn/3dtiles/qx-teh/tileset.json",
		position: { lng: 117.218434, lat: 31.81807, alt: 163 },
		editHeight: -130.0, // 相对高度 (单位：米)，基于 压平/淹没区域 最低点高度的偏移量
		maximumScreenSpaceError: 16,
		dynamicScreenSpaceError: true,
		cullWithChildrenBounds: false,
		skipLevelOfDetail: true,
		preferLeaves: true,
		center: { lat: 31.795308, lng: 117.21948, alt: 1820, heading: 0, pitch: -39 },
		flat: {
			enabled: true
		},
		flyTo: true
	});
	map.addLayer(tilesetLayer);
};
const showDytDemo = () => {
	// 加模型
	tilesetLayer = new mars3d.layer.TilesetLayer({
		name: "大雁塔",
		url: "//data.mars3d.cn/3dtiles/qx-dyt/tileset.json",
		position: { lng: 108.963363, lat: 34.221298, alt: -27 },
		maximumScreenSpaceError: 1,

		// 可传入TilesetFlat构造参数，下面是演示压平区域
		flat: {
			area: [
				{
					positions: [
						[108.962938, 34.221141, 402.4],
						[108.963847, 34.221141, 402.4],
						[108.963847, 34.221868, 402.4],
						[108.962938, 34.221868, 402.4]
					]
				}
			],
			editHeight: 420 // 相对高度 (单位：米)，基于 压平/淹没区域 最低点高度的偏移量
		},
		flyTo: true
	});
	map.addLayer(tilesetLayer);
};
// 绘制剖切面
const drawSectionPoly = () => {
	modelPlanClip.clear();
	map.graphicLayer.startDraw({
		type: "polygon",
		style: {
			color: "#007be6",
			opacity: 0.5,
			outline: true,
			outlineWidth: 2,
			addHeight: 0.5
		},
		success: function (graphic: any) {
			// 绘制成功后回调
			const positions = graphic.positionsShow;
			graphicLayer.clear();

			modelPlanClip.clipOutSide = allProperty.value.clipOutSide;
			modelPlanClip.positions = positions;
		}
	});
};
// 绘制剖切线
const drawSectionLine = () => {
	modelPlanClip.clear();

	map.graphicLayer.startDraw({
		type: "polyline",
		maxPointNum: 2,
		style: {
			color: "#007be6",
			opacity: 0.8,
			outline: false
		},
		success: function (graphic: any) {
			// 绘制成功后回调
			const positions = graphic.positionsShow;
			graphicLayer.clear();

			modelPlanClip.positions = positions;
		}
	});
};
// 模型剖切数据改变
const modelSectionOperate = (e: any, label: any) => {
	if (label == "sectionDistance") {
		modelPlanClip["distance"] = e;
	} else if (label == "type") {
		modelPlanClip["type"] = mars3d.ClipType[e];
	} else {
		modelPlanClip[label] = e;
	}
};
// 图上选中模型
const selectModal = () => {
	// 拾取点位
	graphicLayer.startDraw({
		type: "point",
		style: {
			color: "#00fff2"
		},
		success: (graphic: any) => {
			console.log(graphic);
			const modal = graphic.point?.alt;
		}
	});
};
// 坡向坡度数据操作
const slopeAspectOperate = (e: any, label: any) => {
	contourLine[label] = e;
};
// 绘制多边形坡向坡度
const btnSlopeAspectDraw = () => {
	slope.clear();
	contourLine.clear();
	graphicLayer.startDraw({
		type: "polygon",
		style: {
			color: "#29cf34",
			opacity: 0.3,
			outline: true,
			outlineColor: "#ffffff",
			clampToGround: true
		},
		success: function (graphic: any) {
			// 绘制成功后回调
			const positions = graphic.positionsShow;
			graphicLayer.clear();

			console.log("绘制坐标为", JSON.stringify(mars3d.LngLatArray.toArray(positions))); // 方便测试拷贝坐标

			contourLine.positions = positions;
			slope.add(positions, {
				splitNum: allProperty.value.splitNum, // splitNum插值分割的个数
				radius: 1, // 缓冲半径（影响坡度坡向的精度）
				count: 4 // 缓冲的数量（影响坡度坡向的精度）会求周边(count*4)个点
			});
		}
	});
};
// 绘制矩形坡向坡度
const btnSlopeAspectDrawExtent = () => {
	slope.clear();
	contourLine.clear();
	graphicLayer.startDraw({
		type: "rectangle",
		style: {
			color: "#007be6",
			opacity: 0.5,
			outline: false
		},
		success: (graphic: any) => {
			const positions = graphic.getOutlinePositions(false);
			graphicLayer.clear();

			console.log("绘制坐标为", JSON.stringify(mars3d.LngLatArray.toArray(positions))); // 方便测试拷贝坐标

			contourLine.positions = positions;
			slope.add(positions, {
				splitNum: allProperty.value.splitNum, // splitNum插值分割的个数
				radius: 1, // 缓冲半径（影响坡度坡向的精度）
				count: 4 // 缓冲的数量（影响坡度坡向的精度）会求周边(count*4)个点
			});
		}
	});
};
// 地下透明数据操作
const surfaceOpacityOperate = (e: any, label: any) => {
	underground[label] = e;
};
// 地形开挖---多边形
const btnDraw = () => {
	graphicLayer.startDraw({
		type: "polygon",
		style: {
			color: "#007be6",
			opacity: 0.5,
			outline: false
		},
		attr: {
			key: "terrainClip",
			diffHeight: allProperty.value.diffHeight
		},
		success: (graphic: any) => {
			const positions = graphic.positionsShow;
			graphicLayer.clear();

			console.log(JSON.stringify(mars3d.LngLatArray.toArray(positions))); // 打印下边界
			// 挖地区域
			const areaItem = terrainClip.addArea(positions);
		}
	});
};
// 地形开挖---矩形
const btnDrawExtent = () => {
	graphicLayer.startDraw({
		type: "rectangle",
		style: {
			color: "#007be6",
			opacity: 0.8
		},
		attr: {
			key: "terrainClip",
			diffHeight: allProperty.value.diffHeight
		},
		success: (graphic: any) => {
			const positions = graphic.getOutlinePositions(false);
			graphicLayer.clear();

			console.log(JSON.stringify(mars3d.LngLatArray.toArray(positions))); // 打印下边界

			// 挖地区域
			const areaItem = terrainClip.addArea(positions);
		}
	});
};
// 地形开挖数据操作
const areaOperate = (e: any, label: any) => {
	terrainClip[label] = allProperty.value.diffHeight;
};
// 获取点选高度
const selectHeight = () => {
	if (!measureVolume || !measure) {
		ElMessage("请先开始方量分析");
	}
	// 拾取高度
	graphicLayer.startDraw({
		type: "point",
		style: {
			color: "#00fff2"
		},
		success: (graphic: any) => {
			console.log(666);
			const height = graphic.point?.alt;
			graphicLayer.removeGraphic(graphic);
			if (!height) {
				return;
			}
			console.log(height, "777888");
			measureVolume.height = height;
			showHeightVal();
		}
	});
};
// 显示方量分析点选高度
const showHeightVal = () => {
	const baseHeight = measureVolume.height.toFixed(1);
	const minHeight = measureVolume.minHeight.toFixed(1);
	const maxHeight = measureVolume.maxHeight.toFixed(1);
	allProperty.value.height = baseHeight;
	allProperty.value.minHeight = minHeight;
	allProperty.value.maxHeight = maxHeight;
};
// 绘制方量分析区域
const addVolume = () => {
	measure
		.volume({
			splitNum: 6, // 面内插值次数，控制精度[注意精度越大，分析时间越长]
			// minHeight: 50 , //可以设置一个固定的最低高度
			exact: false
		})
		.then((e: any) => {
			measureVolume = e;
			showHeightVal();
		});
};
// 方量分析数据操作
const volumeOperate = (e: any, label: any) => {
	console.log(e, label);
	if (label == "minHeight" && e > measureVolume.height) {
		ElMessage("墙底部高度不能高于基准面高");
		return;
	}
	if (label == "maxHeight") {
		const maxHeight = Math.ceil(measureVolume.polygonMaxHeight * 10) / 10;
		if (e < maxHeight) {
			ElMessage("墙顶部高度不能低于区域内的地表高" + maxHeight);
			measureVolume.maxHeight = Number(maxHeight);
			return;
		}
		if (e < measureVolume.height) {
			ElMessage("墙顶部高度不能低于基准面高");
			return;
		}
	}
	measureVolume[label] = e;
};
// 清楚地图指定效果
const clearShow = () => {
	console.log(selectedName.value);
	if (selectedName.value == "可视域") {
		graphicLayer.getGraphics().map(item => {
			if (item.type == "viewShed") {
				graphicLayer.removeGraphic(item);
			}
		});
	} else if (selectedName.value == "方量分析") {
		measure.clear();
		measureVolume = null;
	} else if (selectedName.value == "地形开挖") {
		terrainClip.clear();
	} else if (selectedName.value == "坡度坡向") {
		slope.clear();
		contourLine.clear();
	} else if (selectedName.value == "模型剖切") {
		modelPlanClip.clear();
	} else if (selectedName.value == "模型压平") {
		console.log(tilesetLayer);
		tilesetLayer && tilesetLayer.remove(true);
	} else if (selectedName.value == "限高分析") {
		limitHeight.clear();
		graphicLayer.clear();
	}
};
// 添加可视域
const addviewShed = () => {
	// 开始绘制
	graphicLayer.startDraw({
		id: "100",
		type: "viewShed",
		style: {
			angle: 60,
			angle2: 45,
			distance: allProperty.value.distance,
			heading: allProperty.value.heading,
			showFrustum: allProperty.value.showFrustum,
			pitch: -12,
			addHeight: 0.5 // 在坐标点增加的高度值，规避遮挡，效果更友好
		}
	});
};
// 可视域属性值操作
const viewShedOperate = (e: any, label: any) => {
	console.log(e, label);
	const updateView = graphicLayer.getGraphicById("100");
	updateView[label] = e;
};
// 返回主菜单
const backMainMenu = () => {
	const name = selectedName.value;
	console.log(name);
	if (name == "日照分析") {
		shadows.remove(true);
	} else if (name == "可视域") {
	} else if (name == "方量分析") {
	} else if (name == "地形开挖") {
		// terrainClip.clear(); // 清除挖地区域
	} else if (name == "地表透明") {
		underground.remove(); // 清除地表透明
		allProperty.value.enabled = false;
	} else if (name == "坡度坡向") {
		slope.clear();
		contourLine.clear();
	} else if (name == "模型剖切") {
		modelPlanClip.clear();
	} else if (name == "模型压平") {
		tilesetLayer && tilesetLayer.remove(true);
	} else if (name == "限高分析") {
	}
	mainMenuShow.value = true;
	subMenuShow.value = false;
};
// 日照播放或暂停
const playOrPause = () => {
	if (sunshineText.value == "播放") {
		const currentTime = new Date(`${allProperty.value.currDate} ${hours}:${minutes}:00`);
		shadows.time = currentTime;
		const startDate = new Date(allProperty.value.currDate + " 00:00:00");
		const endDate = new Date(allProperty.value.currDate + " 23:59:59");
		shadows.multiplier = 1600;
		shadows.start(startDate, endDate, currentTime);
		sunshineText.value = "暂停";
	} else {
		if (shadows && shadows.isStart) {
			shadows.pause();
			sunshineText.value = "播放";
		}
	}
};
// 日照时间操作
const timeChange = (e: any) => {
	const dateTime = new Date(`${allProperty.value.currDate} ${hours.value}:${minutes.value}:00`);
	shadows.time = dateTime;
};
const closeDiv = () => {
	emits("hiddenConfim");
};
const mapOperate = (name: any) => {
	console.log(name);
	selectedName.value = name;
	if (name == "日照分析") {
		shadows = new mars3d.thing.Shadows({
			multiplier: 1600
		});
		map.addThing(shadows);
		shadows.on(mars3d.EventType.change, function (e: any) {
			allProperty.value.timeVal = shadows.time.getHours() * 60 + shadows.time.getMinutes();
		});
	} else if (name == "可视域") {
		map.addLayer(graphicLayer);
	} else if (name == "方量分析") {
	} else if (name == "地形开挖") {
	} else if (name == "地表透明") {
		// 地下透明
		map.scene.contextOptions = { webgl: { alpha: true } };
		underground = new mars3d.thing.Underground({
			enabled: false
		});
		map.addThing(underground);
	} else if (name == "坡度坡向") {
		slope = new mars3d.thing.Slope({
			arrow: {
				scale: 0.3, // 箭头长度的比例（范围0.1-0.9）
				color: Cesium.Color.YELLOW,
				width: 15, // 箭头宽度
				// materialType: mars3d.MaterialType.LineFlow,
				// materialOptions: {
				//   color: "#1a9850",
				//   image: "img/textures/line-arrow-right.png",
				//   speed: 10
				// },
				// clampToGround: true,
				show: true
			},
			tooltip: function (event) {
				const attr = event.graphic?.attr;
				return `坡度: ${attr.slopeStr1}  (${attr.slopeStr2})<br />坡向: ${attr.direction}°`;
			}
		});
		map.addThing(slope);
	} else if (name == "模型剖切") {
		map.scene.center = { lat: 31.841619, lng: 117.140395, alt: 1259, heading: 90, pitch: -51 };
		// 加模型
		const graphic = new mars3d.graphic.ModelPrimitive({
			position: [117.150365, 31.841954, 50.26],
			style: {
				url: "//data.mars3d.cn/gltf/mars/dikuai/d1.gltf",
				scale: 1
			}
		});
		graphicLayer.addGraphic(graphic);
		modelPlanClip = new mars3d.thing.ModelPlanClip({
			graphic: graphic,
			height: 1, // 开挖的深度
			clipOutSide: false,
			edgeColor: Cesium.Color.GREY,
			edgeWidth: 2.0
		});
		map.addThing(modelPlanClip);
	} else if (name == "模型压平") {
	} else if (name == "限高分析") {
		// 限高分析
		map.fixedLight = true; // 固定光照，避免gltf模型随时间存在亮度不一致。
		// 限高分析类
		limitHeight = new mars3d.thing.LimitHeight({
			color: "rgba(255,0,0,0.5)",
			height: 80, // 限高
			bottomHeight: 32, // 模型地面的海拔高度（单位：米）
			positions: [
				[117.210446, 31.829032, 0],
				[117.226334, 31.826662, 0],
				[117.226694, 31.807882, 0],
				[117.209776, 31.808359, 0],
				[117.209778, 31.808341, 0]
			]
		});
		map.addThing(limitHeight);
	}
	mainMenuShow.value = false;
	subMenuShow.value = true;
};
onUnmounted(() => {
	map = null;
	measure = null;
	measureVolume = null;
	shadows = null;
	graphicLayer = null;
});
</script>

<style scoped lang="scss">
@mixin flex {
	display: flex;
	align-items: center;
}
// 菜单弹框出现动画
@keyframes fadeIn {
	0% {
		opacity: 0;
		transform: translate3d(100%, 0, 0);
	}
	100% {
		opacity: 1;
		transform: none;
	}
}
.main-content {
	position: absolute;
	top: 60px;
	right: 10px;
	padding: 0 !important;
	background-image: none !important;
	border: 1px solid #008aff70;
	border-radius: 2px !important;
	background-color: rgba(23, 49, 71, 0.8);
	// min-width: 300px;
	min-height: 370px;
	box-shadow: 0 4px 15px 1px #02213bb3;
	animation: fadeIn 1s;
	&-title {
		@include flex;
		width: 100%;
		height: 40px;
		padding: 0 5px 0 10px;
		background-image: url("@/assets/images/Mars3DIcon/subClassTitle.png");
		background-size: 100% 100%;
		background-repeat: no-repeat;
		span {
			font-size: 16px;
			color: #0089fe;
			margin-right: auto;
		}
		:deep() {
			.el-icon {
				cursor: pointer;
			}
		}
	}
	&-menu {
		width: 300px;
		height: max-content;
		display: flex;
		justify-content: center;
		flex-wrap: wrap;
		overflow-y: scroll;
		.menu-item {
			display: inline-block;
			width: 75px;
			margin-top: 20px;
			margin-left: 10px;
			vertical-align: top;
			text-align: center;
			cursor: pointer;
			font-size: 12px;
			color: white;
			.icon {
				width: 50px;
				height: 50px;
				padding: 1px;
			}
		}
	}
	.operate-content {
		width: 100%;
		height: calc(100% - 40px);
		> div {
			width: 300px;
			padding: 10px;
			.title {
				color: #fff;
				padding-top: 10px;
				padding-bottom: 4px;
				border-bottom: 1px dotted white;
				@include flex;
				.back {
					margin: 0 10px;
					cursor: pointer;
				}
				.delete {
					margin-right: 10px;
					cursor: pointer;
				}
				> span {
					font-size: 14px;
					margin-right: auto;
				}
			}
			.subtitle-tip {
				color: #cad1d1;
				padding-top: 5px;
				margin-bottom: 15px;
			}
			.item-classify {
				display: flex;
				flex-direction: column;
				&-item {
					display: flex;
					align-items: center;
					color: white;
					margin-bottom: 10px;
					* {
						margin-right: 10px;
					}
					:deep() {
						.el-slider,
						.el-date-editor {
							width: 60% !important;
						}
						.el-input-number {
							width: 50%;
						}
						.el-checkbox__inner,
						.el-radio__inner {
							background-color: transparent;
						}
						.el-checkbox__label,
						.el-radio__label {
							color: white;
						}
					}
				}
			}
			.sunshing-play {
				@include flex;
				justify-content: center;
				margin-top: 10px;
			}
			.volume-operate {
				@include flex;
				justify-content: center;
				margin-top: 10px;
				:deep() {
					.el-button {
						margin-left: 10px;
					}
				}
			}
		}
		.volumeAnalysis {
			width: 400px;
		}
	}
}
// element 组件样式
:deep() {
	.el-input__wrapper {
		background-color: transparent;
	}
	.el-input__inner {
		color: white;
	}
	.el-input-number__increase,
	.el-input-number__decrease {
		background-color: transparent;
		color: white;
	}
	.el-button {
		background: rgba(51, 89, 181, 0.6);
		border-radius: 6px;
		border: 0;
	}
}
</style>
