农作物管理系统(openlayers、python、django)

2024-01-28 15:58

本文主要是介绍农作物管理系统(openlayers、python、django),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

农作物管理系统(openlayers、python、django)

    • 客户需求
    • 原始数据
    • 软件安装
    • 服务发布
    • 源码
    • 功能界面

客户需求

项目名称是:农作物长势遥感监测信息发布平台

  1. 农作物长势分析:做成下拉菜单,下拉菜单里面是月份。点击地块之后可以出现每个月份的长势图(是曲线图)
  2. 农作物分类:农作物共分了6类,也可以做成下拉菜单,点击菜单出现棉花,玉米等类,在点击下拉菜单的时候可以在图中显示对应的种类。
  3. 农作物面积:也是下拉菜单,也主要是棉花,玉米,小麦等5类作物面积。在点击下拉菜单时出现地块和面积统计数据。(要是地块数据不好显示可以只做显示面积数据)
  4. 用户在点击每个地块数据时可以给用户显示地块的种植类和面积已经属于那个乡镇
  5. 定位用户的地理位置,可以显示该位置的地块信息(如果是耕地就显示,不是耕地就不用显示了)
  6. 地图常用的放大缩小功能,和搜索查询功能

以上是原始需求,实现上做了一些改动

原始数据

原始数据,点我

软件安装

  1. 用于发布地图服务java环境:Tomcat + geoserver + jdk
  2. 用于后端python
  3. 用于前端nodejs
  4. 开发工具visual studio code、pycharm等

服务发布

简单发布shp 和 tif影像数据wms服务即可
在这里插入图片描述

源码

前端主要是react+dva+umi+antdesign框架

前端 核心源码 pages/openlayers_nongye/index.js

/* global mars3d Cesium*/
import React, { Component } from 'react';
import { connect } from 'dva';
import { Divider, Checkbox, Button, Row, Col, Tooltip, Modal, Select, Tree,Icon } from 'antd'
import styles from './style.less'
import echarts from 'echarts'
import Pie from './pie'
import Source from './source'const { TreeNode } = Tree;/* openlayers */
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import Feature from 'ol/Feature';
import { OSM, XYZ } from 'ol/source';
import { LineString, Point, Polygon } from 'ol/geom';
import { defaults as defaultInteractions, Pointer as PointerInteraction } from 'ol/interaction';
import { Image as ImageLayer,Tile as TileLayer, Vector as VectorLayer } from 'ol/layer';
import { ImageWMS ,TileJSON, Vector as VectorSource } from 'ol/source';
import { Fill, Stroke, Style } from 'ol/style';
import { toLonLat, fromLonLat, get } from 'ol/proj';
import { FullScreen } from 'ol/control';
import filter,{or,like,and, equalTo} from 'ol/format/filter';
import GeoJSON from 'ol/format/GeoJSON';
import { none } from 'ol/centerconstraint';const chinaJson = require('./file/wuhan.geojson')
const { Option, OptGroup } = Select;@connect(({ nongye }) => ({nongye
}))class Nongye extends Component {constructor(props) {super(props)this.state = {map: null,chart: null,//底图digitalLayer: new TileLayer({//source: new OSM()source: new XYZ({url: 'https://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}'})}),imagesLayer: new TileLayer({//source: new OSM()source: new XYZ({url: 'https://wprd0{1-4}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=6&x={x}&y={y}&z={z}'})}),arcgisLayer: new TileLayer({source: new XYZ({//url: 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'url: 'http://cache1.arcgisonline.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}'})}),//业务图层wushuImage:new ImageLayer({source: new ImageWMS({url: '/nongye/geoserver/nongye/wms',params: {'LAYERS': 'nongye:geotiff_coverage'},ratio: 1,serverType: 'geoserver',crossOrigin: 'anonymous',}),}),wushuBoundary:new ImageLayer({source: new ImageWMS({url: '/nongye/geoserver/nongye/wms',params: {'LAYERS': 'nongye:wusubound'},ratio: 1,serverType: 'geoserver',crossOrigin: 'anonymous',}),}),wushuCrops:new ImageLayer({source: new ImageWMS({url: '/nongye/geoserver/nongye/wms',params: {'LAYERS': 'nongye:wusugd',// 'CQL_FILTER': `kind='mianhua'`},ratio: 1,serverType: 'geoserver',crossOrigin: 'anonymous',}),}),wuhanGeojson: new VectorLayer({source: new VectorSource({url: chinaJson,format: new GeoJSON()}),style: new Style({stroke: new Stroke({color: '#319FD3',width: 20})})}),showChart: false,crop_prop:null,//点击地块详细信息}}componentDidMount() {this.start()this.setState({chart: this.refs.chart})}start = () => {this.initMap({}).then(() => {const {map,wushuCrops} = this.state//监听动作let that = thismap.on('singleclick', function (evt) {// document.getElementById('info').innerHTML = '';var viewResolution = /** @type {number} */ (map.getView().getResolution());var url = wushuCrops.getSource().getFeatureInfoUrl(evt.coordinate,viewResolution,'EPSG:3857',{'INFO_FORMAT': 'application/json'});if (url) {fetch(url).then(function (response) { return response.text(); }).then(function (result) {console.log(result)let json =JSON.parse(result)that.setState({showChart:false,crop_prop:json.features.length>0 ?json.features[0].properties:null})});}});map.on('pointermove', function (evt) {if (evt.dragging) {return;}var pixel = map.getEventPixel(evt.originalEvent);var hit = map.forEachLayerAtPixel(pixel, function () {return true;});map.getTargetElement().style.cursor = hit ? 'pointer' : '';});})}initMap = () => {const { wuhanGeojson, arcgisLayer, imagesLayer, digitalLayer,wushuBoundary,wushuImage,wushuCrops } = this.statearcgisLayer.set('id', 'arcgisLayer')arcgisLayer.setVisible(false)imagesLayer.set('id', 'imagesLayer')imagesLayer.setVisible(false)digitalLayer.set('id', 'digitalLayer')digitalLayer.setVisible(true)wushuImage.set("id",'wushuImage')wushuImage.setVisible(false)wushuBoundary.set("id",'wushuBoundary')wushuBoundary.setVisible(false)wushuCrops.set("id",'wushuCrops')wushuCrops.setVisible(true)return new Promise(resolve => {var fullScreenControl = new FullScreen()var map = new Map({interactions: defaultInteractions().extend([new Drag()]),view: new View({center: fromLonLat([84.41,44.60]),zoom: 9}),layers: [arcgisLayer,imagesLayer,digitalLayer,wuhanGeojson,wushuImage,wushuBoundary,wushuCrops,],target: 'map'});map.addControl(fullScreenControl)this.setState({map},()=>{resolve()})})};//定位location =()=>{const {map} = this.statelet bmap = new BMap.Map("allmap");var geolocation = new BMap.Geolocation();geolocation.getCurrentPosition(function(r){if(this.getStatus() == BMAP_STATUS_SUCCESS){// alert('您的位置:'+r.point.lng+','+r.point.lat);map.setView(new View({center: fromLonLat([r.point.lng,r.point.lat]),zoom: 10}))}else {alert('failed'+this.getStatus());}});}//影像和电子地图切换anhei = () => {const { map, arcgisLayer } = this.statevar layers = map.getLayers()for (let i = 0; i < layers.getLength(); i++) {var id = layers.item(i).get('id')if (id === 'imagesLayer' || id === 'digitalLayer') {layers.item(i).setVisible(false)}}arcgisLayer.setVisible(true)}weixing = () => {const { map, imagesLayer } = this.statevar layers = map.getLayers()for (let i = 0; i < layers.getLength(); i++) {var id = layers.item(i).get('id')if (id === 'arcgisLayer' || id === 'digitalLayer') {layers.item(i).setVisible(false)}}imagesLayer.setVisible(true)}luwang = () => {const { map, digitalLayer } = this.statevar layers = map.getLayers()for (let i = 0; i < layers.getLength(); i++) {var id = layers.item(i).get('id')if (id === 'arcgisLayer' || id === 'imagesLayer') {layers.item(i).setVisible(false)}}digitalLayer.setVisible(true)}onCheck = (checkedKeys, info) => {const {wushuCrops,wushuImage,wushuBoundary} = this.state//显示隐藏图层数据if(checkedKeys.includes("wushu")){//两者皆有wushuImage.setVisible(true)wushuBoundary.setVisible(true)}else if (checkedKeys.includes("image")) { //只有影像wushuImage.setVisible(true)wushuBoundary.setVisible(false)}else if(checkedKeys.includes("boundary")){ //只有边界wushuImage.setVisible(false)wushuBoundary.setVisible(true)}else{wushuImage.setVisible(false)wushuBoundary.setVisible(false)}//过滤crops业务图层要素数据let p = ''checkedKeys.forEach(element => {p += "'"+element+"' ,"});wushuCrops.getSource().updateParams({'CQL_FILTER': `kind in ${'('+p.substr(0,p.length-1)+')'}`})wushuCrops.getSource().refresh()};getArrDifference =(arr1, arr2)=> {return arr1.concat(arr2).filter(function(v, i, arr) {return arr.indexOf(v) === arr.lastIndexOf(v);});} tongji =()=>{const {crop_prop } = this.statethis.setState({showChart:true},()=>{getFromCache("tongjiArea").then(data=>{if(!data){this.props.dispatch({type: 'nongye/getTongjiArea',payload: {},}).then(result => {setToCache("tongjiArea",result)this.initBar(result.data)})}else{this.initBar(data.data)}})})}initBar = (data)=>{var myChart = echarts.init(document.getElementById('chart'));var option = {title: {text: '农作物面积统计(平方米)'},tooltip: {},xAxis: {type: 'category',data: ['棉花', '番茄', '蔬菜','小麦','玉米','其他']},yAxis: {type: 'value'},grid: {bottom: '10%',left: '3%',containLabel: true},series: [{data: [data['mianhua'],data['fanqie'],data['shucai'],data['xiaomai'],data['yumi'],data['qita']],type: 'bar'}]};myChart.setOption(option);}zhangshi = () =>{const {crop_prop } = this.statethis.setState({showChart:true},()=>{var myChart = echarts.init(document.getElementById('chart'));var option = {title: {text: '长势'},tooltip: {},xAxis: {type: 'category',data: ['3月', '5月', '6月','7月','8月','9月','10月']},yAxis: {type: 'value'},grid: {bottom: '10%',containLabel: true},series: [{data: [crop_prop.b1_all_tif, crop_prop.b2_all_tif,crop_prop.b3_all_tif,crop_prop.b4_all_tif,crop_prop.b5_all_tif,crop_prop.b6_all_tif,crop_prop.b7_all_tif],type: 'line'}]};myChart.setOption(option);})}NDVI = () =>{const {crop_prop } = this.statethis.setState({showChart:true},()=>{var myChart = echarts.init(document.getElementById('chart'));var option = {title: {text: 'NDVI'},tooltip: {},grid: {bottom: '10%',containLabel: true},xAxis: {type: 'category',data: ['3月12', '4月11', '5月26','6月20','7月10','8月24','9月3','10月18']},yAxis: {type: 'value'},series: [{data: [crop_prop.b1_ndvi202 ,crop_prop.b2_ndvi202	,crop_prop.b3_ndvi202	,crop_prop.b4_ndvi202	,crop_prop.b5_ndvi202	,crop_prop.b6_ndvi202	,crop_prop.b7_ndvi202	,crop_prop.b8_ndvi202],type: 'line'}]};myChart.setOption(option);})}render() {const { map, chart,crop_prop,showChart } = this.statereturn (<div style={{ width: '100%', paddingTop: '80px' }}><div className={styles.layer}><TreecheckabledefaultExpandedKeys={['wushu','crops']}defaultSelectedKeys={['crops']}defaultCheckedKeys={['crops']}// onSelect={this.onSelect}onCheck={this.onCheck}><TreeNode title="乌苏区位图" key="wushu"><TreeNode title="影像" key="image"></TreeNode><TreeNode title="边界" key="boundary"></TreeNode></TreeNode><TreeNode title="全部农作物" key="crops"><TreeNode title="番茄" key="fanqie"></TreeNode><TreeNode title="棉花" key="mianhua"></TreeNode><TreeNode title="蔬菜" key="shucai"></TreeNode><TreeNode title="小麦" key="xiaomai"></TreeNode><TreeNode title="玉米" key="yumi"></TreeNode><TreeNode title="其他" key="qita"></TreeNode></TreeNode></Tree><Divider orientation="right"><a onClick={this.tongji}>统计面积</a></Divider><div className={styles.desc}>{ crop_prop && (<>{/* <div className={styles.title}>农作物详情</div> */}<Divider orientation="left">农作物详情</Divider><div className={styles.item}><label>乡镇:</label><span>{crop_prop.xiangzhen}</span></div><div className={styles.item}><label>土地:</label><span>{crop_prop.classname}</span></div><div className={styles.item}><label>类型:</label><span>{crop_prop.kind}</span></div><div className={styles.item}><label>面积:</label><span>{crop_prop.Shape_Area}</span></div><div className={styles.item}><label>编码:</label><span>{crop_prop.code}</span></div><Divider orientation="right"><a onClick={this.zhangshi}>查看长势</a></Divider><Divider orientation="right"><a onClick={this.NDVI}>查看NDVI</a></Divider></>)}</div>{showChart && (<div className={styles.chart}><div id="chart" ref="chart" style={{ width: '100%',height:'100%' }}></div></div>)}</div><div className={styles.map} id="map"><div className={styles.toolbar}><div className={styles.bar} onClick={this.location}><div id="allmap" style={{display:none}}></div><p><Icon type="environment" /></p></div><div className={styles.bar} onClick={this.anhei}><p>暗黑</p></div><div className={styles.bar} onClick={this.luwang}><p>路网</p></div><div className={styles.bar} onClick={this.weixing}><p>卫星</p></div></div></div></div>)}
}var Drag = /*@__PURE__*/(function (PointerInteraction) {function Drag() {PointerInteraction.call(this, {handleDownEvent: handleDownEvent,handleDragEvent: handleDragEvent,handleMoveEvent: handleMoveEvent,handleUpEvent: handleUpEvent});/*** @type {import("../src/ol/coordinate.js").Coordinate}* @private*/this.coordinate_ = null;/*** @type {string|undefined}* @private*/this.cursor_ = 'pointer';/*** @type {Feature}* @private*/this.feature_ = null;/*** @type {string|undefined}* @private*/this.previousCursor_ = undefined;}if (PointerInteraction) Drag.__proto__ = PointerInteraction;Drag.prototype = Object.create(PointerInteraction && PointerInteraction.prototype);Drag.prototype.constructor = Drag;return Drag;
}(PointerInteraction));/*** @param {import("../src/ol/MapBrowserEvent.js").default} evt Map browser event.* @return {boolean} `true` to start the drag sequence.*/
function handleDownEvent(evt) {var map = evt.map;var feature = map.forEachFeatureAtPixel(evt.pixel,function (feature) {return feature;});if (feature) {this.coordinate_ = evt.coordinate;this.feature_ = feature;}return !!feature;
}/*** @param {import("../src/ol/MapBrowserEvent.js").default} evt Map browser event.*/
function handleDragEvent(evt) {var deltaX = evt.coordinate[0] - this.coordinate_[0];var deltaY = evt.coordinate[1] - this.coordinate_[1];var geometry = this.feature_.getGeometry();geometry.translate(deltaX, deltaY);this.coordinate_[0] = evt.coordinate[0];this.coordinate_[1] = evt.coordinate[1];
}/*** @param {import("../src/ol/MapBrowserEvent.js").default} evt Event.*/
function handleMoveEvent(evt) {if (this.cursor_) {var map = evt.map;var feature = map.forEachFeatureAtPixel(evt.pixel,function (feature) {return feature;});var element = evt.map.getTargetElement();if (feature) {if (element.style.cursor != this.cursor_) {this.previousCursor_ = element.style.cursor;element.style.cursor = this.cursor_;}} else if (this.previousCursor_ !== undefined) {element.style.cursor = this.previousCursor_;this.previousCursor_ = undefined;}}
}/*** @return {boolean} `false` to stop the drag sequence.*/
function handleUpEvent() {this.coordinate_ = null;this.feature_ = null;return false;
}export default Nongye

后端主要采用django框架写的接口
后端 核心代码在这里插入图片描述

功能界面

在这里插入图片描述

说明:
左侧目录树对图层进行隐藏,影像/边界是单独图层,农作物整是一个图层,分了不同类别,这里有区别;
统计面积是统计上面农作物分类的面积,这里统计一次后写入indexdb,方便下次快速读取
点击地块左侧显示地块的详细信息,包括可查看长势图和nvdi图

如有兴趣, 能帮到您,联系我 qq:851356263 ,请说明来意,谢谢!

这篇关于农作物管理系统(openlayers、python、django)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/654097

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

如何用Docker运行Django项目

本章教程,介绍如何用Docker创建一个Django,并运行能够访问。 一、拉取镜像 这里我们使用python3.11版本的docker镜像 docker pull python:3.11 二、运行容器 这里我们将容器内部的8080端口,映射到宿主机的80端口上。 docker run -itd --name python311 -p

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

【机器学习】高斯过程的基本概念和应用领域以及在python中的实例

引言 高斯过程(Gaussian Process,简称GP)是一种概率模型,用于描述一组随机变量的联合概率分布,其中任何一个有限维度的子集都具有高斯分布 文章目录 引言一、高斯过程1.1 基本定义1.1.1 随机过程1.1.2 高斯分布 1.2 高斯过程的特性1.2.1 联合高斯性1.2.2 均值函数1.2.3 协方差函数(或核函数) 1.3 核函数1.4 高斯过程回归(Gauss

【学习笔记】 陈强-机器学习-Python-Ch15 人工神经网络(1)sklearn

系列文章目录 监督学习:参数方法 【学习笔记】 陈强-机器学习-Python-Ch4 线性回归 【学习笔记】 陈强-机器学习-Python-Ch5 逻辑回归 【课后题练习】 陈强-机器学习-Python-Ch5 逻辑回归(SAheart.csv) 【学习笔记】 陈强-机器学习-Python-Ch6 多项逻辑回归 【学习笔记 及 课后题练习】 陈强-机器学习-Python-Ch7 判别分析 【学

nudepy,一个有趣的 Python 库!

更多资料获取 📚 个人网站:ipengtao.com 大家好,今天为大家分享一个有趣的 Python 库 - nudepy。 Github地址:https://github.com/hhatto/nude.py 在图像处理和计算机视觉应用中,检测图像中的不适当内容(例如裸露图像)是一个重要的任务。nudepy 是一个基于 Python 的库,专门用于检测图像中的不适当内容。该

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

工厂ERP管理系统实现源码(JAVA)

工厂进销存管理系统是一个集采购管理、仓库管理、生产管理和销售管理于一体的综合解决方案。该系统旨在帮助企业优化流程、提高效率、降低成本,并实时掌握各环节的运营状况。 在采购管理方面,系统能够处理采购订单、供应商管理和采购入库等流程,确保采购过程的透明和高效。仓库管理方面,实现库存的精准管理,包括入库、出库、盘点等操作,确保库存数据的准确性和实时性。 生产管理模块则涵盖了生产计划制定、物料需求计划、

pip-tools:打造可重复、可控的 Python 开发环境,解决依赖关系,让代码更稳定

在 Python 开发中,管理依赖关系是一项繁琐且容易出错的任务。手动更新依赖版本、处理冲突、确保一致性等等,都可能让开发者感到头疼。而 pip-tools 为开发者提供了一套稳定可靠的解决方案。 什么是 pip-tools? pip-tools 是一组命令行工具,旨在简化 Python 依赖关系的管理,确保项目环境的稳定性和可重复性。它主要包含两个核心工具:pip-compile 和 pip

HTML提交表单给python

python 代码 from flask import Flask, request, render_template, redirect, url_forapp = Flask(__name__)@app.route('/')def form():# 渲染表单页面return render_template('./index.html')@app.route('/submit_form',