Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
V
vue-cesium-lyc
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lyc
vue-cesium-lyc
Commits
cc0b55de
Commit
cc0b55de
authored
Aug 08, 2024
by
lyc
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
point封装
parent
8927f7fd
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
453 additions
and
127 deletions
+453
-127
App.vue
src/App.vue
+15
-2
demo.vue
src/components/demo.vue
+126
-125
shiye.vue
src/components/shiye.vue
+84
-0
point.vue
src/encapsulation/point.vue
+86
-0
point.js
src/js/point.js
+142
-0
No files found.
src/App.vue
View file @
cc0b55de
...
...
@@ -15,10 +15,18 @@ import raotaiyang from './components/raotaiyng.vue'
import
qq
from
'./components/qq.vue'
import
setl
from
'./components/setl.vue'
import
xyz
from
'./components/xyz.vue'
import
shiye
from
'./components/shiye.vue'
//封装
import
point
from
'./encapsulation/point.vue'
export
default
{
name
:
'app'
,
components
:
{
boom
,
demo
,
draw
,
moon
,
fire
,
selt
,
sun
,
camera
,
dail
,
baozha
,
kedupan
,
raotaiyang
,
qq
,
setl
,
xyz
}
components
:
{
boom
,
demo
,
draw
,
moon
,
fire
,
selt
,
sun
,
camera
,
dail
,
baozha
,
kedupan
,
raotaiyang
,
qq
,
setl
,
xyz
,
shiye
,
point
}
}
</
script
>
...
...
@@ -36,8 +44,13 @@ export default {
<!--
<dail/>
-->
<!--
<raotaiyang/>
-->
<!--
<qq/>
-->
<
xyz/
>
<
!--
<xyz/>
--
>
<!--
<setl/>
-->
<!--
<shiye/>
-->
<point/>
</
template
>
<
style
scoped
>
...
...
src/components/demo.vue
View file @
cc0b55de
...
...
@@ -10,30 +10,30 @@
import
{
onMounted
}
from
'vue'
import
*
as
Cesium
from
'cesium'
import
{
ref
}
from
'vue'
let
viewer
onMounted
(()
=>
{
Cesium
.
Ion
.
defaultAccessToken
=
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyYTI3MDQxMS1hYzgxLTRlYTQtODExZS00YzdmYjM0YTg3OTAiLCJpZCI6MjI0NzQzLCJpYXQiOjE3MTkzOTcxMDF9._VD-W1rEy7jSUtPmcVytEYbZIZ00_IeHCZm59Kua5aE'
const
viewer
=
new
Cesium
.
Viewer
(
"cesiumContainer"
,
{
viewer
=
new
Cesium
.
Viewer
(
"cesiumContainer"
,
{
terrainProvider
:
Cesium
.
createWorldTerrain
(),
})
// 添加太阳
const
sun
=
new
Cesium
.
Sun
();
viewer
.
scene
.
sun
=
sun
;
// 添加月球
const
moon
=
new
Cesium
.
Moon
();
viewer
.
scene
.
moon
=
moon
;
moon
.
textureUrl
=
"/src/image/坐标.png"
console
.
log
(
moon
.
ellipsoid
,
moon
)
var
entity
=
viewer
.
entities
.
add
({
position
:
Cesium
.
Cartesian3
.
fromDegrees
(
-
75.59777
,
40.03883
,
3044000
),
model
:
{
uri
:
'/src/model/moon.gltf'
,
minimumPixelSize
:
100
,
scale
:
2000.0
,
},
});
viewer
.
zoomTo
(
entity
)
//
//
添加太阳
//
const sun = new Cesium.Sun();
//
viewer.scene.sun = sun;
//
//
添加月球
//
const moon = new Cesium.Moon();
//
viewer.scene.moon = moon;
//
moon.textureUrl="/src/image/坐标.png"
//
console.log(moon.ellipsoid, moon)
//
var entity = viewer.entities.add({
//
position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883,3044000),
//
model: {
//
uri: '/src/model/moon.gltf',
//
minimumPixelSize: 100,
//
scale: 2000.0,
//
},
//
});
//
viewer.zoomTo(entity)
// 让太阳和月球随着时间自动旋转
...
...
@@ -46,82 +46,82 @@ onMounted(() => {
// viewer.shadows = false;
// viewer.scene.sun.show = false;
// var explodeVertexShader =
// `
// attribute vec3 position;
// attribute vec2 textureCoordinates;
// uniform mat4 modelViewMatrix;
// uniform mat4 projectionMatrix;
// varying vec2 vTextureCoordinates;
// void main() {
// gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
// vTextureCoordinates = textureCoordinates;
// }
// `;
// // 自定义爆炸效果的fragment shader
// var explodeFragmentShader =`precision highp float;
// varying vec2 vTextureCoordinates;
// uniform sampler2D uTexture;
// uniform float explosionFactor;
// void main() {
// vec4 texelColor = texture2D(uTexture, vTextureCoordinates);
// texelColor.rgb *= explosionFactor;
// gl_FragColor = texelColor;
// }`;
// // 创建一个材质
// var material = new Cesium.Material({
// fabric: {
// uniforms: {
// color: new Cesium.Color(1.0, 0.0, 0.0, 0.5), // 爆炸效果的颜色和透明度
// explosionFactor: 0.0 // 初始爆炸因子,控制爆炸效果的强度
// },
// source: {
// vertexShaderSource: explodeVertexShader,
// fragmentShaderSource: explodeFragmentShader
// }
// }
// });
// // 创建一个球体实体
// var entity = viewer.entities.add({
// position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
// ellipsoid: {
// radii: new Cesium.Cartesian3(200000.0, 200000.0, 200000.0),
// material: material
// }
// });
// // 定义动画函数,用于控制爆炸效果
// function explodeAnimation() {
// var startTime = Cesium.JulianDate.now();
// viewer.clock.onTick.addEventListener(function (clock) {
// var currentTime = clock.currentTime;
// var deltaTime = Cesium.JulianDate.secondsDifference(currentTime, startTime);
// if (deltaTime >= 0 && deltaTime
<=
5
)
{
// // 更新爆炸因子,逐步增加爆炸效果的强度
// material.uniforms.explosionFactor = deltaTime * 100000.0; // 调整增长速度和最大爆炸范围
// } else if (deltaTime > 5) {
// // 爆炸效果结束后移除实体
// viewer.entities.remove(entity);
// viewer.clock.onTick.removeEventListener(explodeAnimation);
// }
// });
// }
// // 启动爆炸效果动画
// explodeAnimation()
// viewer.zoomTo(entity)
})
// var explodeVertexShader =
// `
// attribute vec3 position;
// attribute vec2 textureCoordinates;
// uniform mat4 modelViewMatrix;
// uniform mat4 projectionMatrix;
// varying vec2 vTextureCoordinates;
// void main() {
// gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
// vTextureCoordinates = textureCoordinates;
// }
// `;
// // 自定义爆炸效果的fragment shader
// var explodeFragmentShader =`precision highp float;
// varying vec2 vTextureCoordinates;
// uniform sampler2D uTexture;
// uniform float explosionFactor;
// void main() {
// vec4 texelColor = texture2D(uTexture, vTextureCoordinates);
// texelColor.rgb *= explosionFactor;
// gl_FragColor = texelColor;
// }`;
// // 创建一个材质
// var material = new Cesium.Material({
// fabric: {
// uniforms: {
// color: new Cesium.Color(1.0, 0.0, 0.0, 0.5), // 爆炸效果的颜色和透明度
// explosionFactor: 0.0 // 初始爆炸因子,控制爆炸效果的强度
// },
// source: {
// vertexShaderSource: explodeVertexShader,
// fragmentShaderSource: explodeFragmentShader
// }
// }
// });
// // 创建一个球体实体
// var entity = viewer.entities.add({
// position: Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883),
// ellipsoid: {
// radii: new Cesium.Cartesian3(200000.0, 200000.0, 200000.0),
// material: material
// }
// });
// // 定义动画函数,用于控制爆炸效果
// function explodeAnimation() {
// var startTime = Cesium.JulianDate.now();
// viewer.clock.onTick.addEventListener(function (clock) {
// var currentTime = clock.currentTime;
// var deltaTime = Cesium.JulianDate.secondsDifference(currentTime, startTime);
// if (deltaTime >= 0 && deltaTime
<=
5
)
{
// // 更新爆炸因子,逐步增加爆炸效果的强度
// material.uniforms.explosionFactor = deltaTime * 100000.0; // 调整增长速度和最大爆炸范围
// } else if (deltaTime > 5) {
// // 爆炸效果结束后移除实体
// viewer.entities.remove(entity);
// viewer.clock.onTick.removeEventListener(explodeAnimation);
// }
// });
// }
// // 启动爆炸效果动画
// explodeAnimation()
// viewer.zoomTo(entity)
//
})
// viewer.scene.postProcessStages.add(new Cesium.PostProcessStage({
// fragmentShader: `
...
...
@@ -240,34 +240,35 @@ onMounted(() => {
// })
// const polyline = viewer.entities.add({
// id: 'polyline',
// polyline: {
// positions: Cesium.Cartesian3.fromDegreesArray([120, 30, 121, 20,121,30]),
// width:2,
// material:Cesium.Color.YELLOW
// }
// })
// let point0 = Cesium.Cartesian3.fromDegrees(120, 10);
// let point1 = Cesium.Cartesian3.fromDegrees(121, 20);
// let point2 = Cesium.Cartesian3.fromDegrees(121, 30);
// let localToWorldMatrix = Cesium.Transforms.eastNorthUpToFixedFrame(point1);
// let worldToLocalMatrix = Cesium.Matrix4.inverse(localToWorldMatrix, new Cesium.Matrix4());
// console.log(localToWorldMatrix,point1,worldToLocalMatrix)
// // 计算 localVector
// let worldVector = Cesium.Cartesian3.subtract(point0, point1, new Cesium.Cartesian3());
// let localVector = Cesium.Matrix4.multiplyByPointAsVector(worldToLocalMatrix, worldVector, new Cesium.Cartesian3());
// console.log(point0,point1,point2)
// console.log(worldVector,localVector)
// // localVector 向量归一化
// let direction = Cesium.Cartesian3.normalize(localVector, new Cesium.Cartesian3());
// console.log(direction)
// let angleToX = Math.atan2(direction.y, direction.x);
// let heading = Cesium.Math.toDegrees(angleToX);
// if (heading > 0) { }
// else heading=360+heading
// console.log(heading)
// const polyline = viewer.entities.add({
// id: 'polyline',
// polyline: {
// positions: Cesium.Cartesian3.fromDegreesArray([100, 10, 121, 20,121,30]),
// width:2,
// material:Cesium.Color.YELLOW
// }
// })
let
point0
=
Cesium
.
Cartesian3
.
fromDegrees
(
120
,
10
);
let
point1
=
Cesium
.
Cartesian3
.
fromDegrees
(
120
,
20
);
let
point2
=
Cesium
.
Cartesian3
.
fromDegrees
(
121
,
30
);
let
localToWorldMatrix
=
Cesium
.
Transforms
.
eastNorthUpToFixedFrame
(
point0
);
let
worldToLocalMatrix
=
Cesium
.
Matrix4
.
inverse
(
localToWorldMatrix
,
new
Cesium
.
Matrix4
());
// console.log(localToWorldMatrix, point1, worldToLocalMatrix)
// 计算 localVector
let
worldVector
=
Cesium
.
Cartesian3
.
subtract
(
point1
,
point0
,
new
Cesium
.
Cartesian3
());
let
localVector
=
Cesium
.
Matrix4
.
multiplyByPointAsVector
(
worldToLocalMatrix
,
worldVector
,
new
Cesium
.
Cartesian3
());
// console.log(point0, point1, point2)
// console.log(worldVector, localVector)
// localVector 向量归一化
let
direction
=
Cesium
.
Cartesian3
.
normalize
(
localVector
,
new
Cesium
.
Cartesian3
());
// console.log(direction)
let
angleToX
=
Math
.
atan2
(
direction
.
y
,
direction
.
x
);
let
heading
=
Cesium
.
Math
.
toDegrees
(
angleToX
);
console
.
log
(
heading
)
if
(
heading
>
0
)
{
}
else
heading
=
360
+
heading
console
.
log
(
heading
)
// const polygon = viewer.entities.add({
// polygon: {
...
...
@@ -280,10 +281,10 @@ onMounted(() => {
// extrudedHeight: 20000,
// fill: false,
// outline: true,
// outlineColor:Cesium.Color.RED
// outlineColor:
Cesium.Color.RED
// }
// })
})
...
...
src/components/shiye.vue
0 → 100644
View file @
cc0b55de
<
template
>
<div
id=
"cesiumContainer"
class=
"all"
></div>
</
template
>
<
script
setup
>
import
{
onMounted
}
from
'vue'
import
*
as
Cesium
from
'cesium'
onMounted
(()
=>
{
Cesium
.
Ion
.
defaultAccessToken
=
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyYTI3MDQxMS1hYzgxLTRlYTQtODExZS00YzdmYjM0YTg3OTAiLCJpZCI6MjI0NzQzLCJpYXQiOjE3MTkzOTcxMDF9._VD-W1rEy7jSUtPmcVytEYbZIZ00_IeHCZm59Kua5aE'
const
viewer
=
new
Cesium
.
Viewer
(
"cesiumContainer"
,
{
})
// 计算圆柱体的中心点
const
position
=
Cesium
.
Cartesian3
.
fromDegrees
(
-
70.001
,
30.001
,
20000
);
// 设置圆柱体的朝向为水平
const
heading
=
Cesium
.
Math
.
toRadians
(
0.0
);
// 朝向(水平)z
const
pitch
=
Cesium
.
Math
.
toRadians
(
0.0
);
// 俯仰角(垂直)y
const
roll
=
Cesium
.
Math
.
toRadians
(
0.0
);
// 滚转角(水平)x
const
hpr
=
new
Cesium
.
HeadingPitchRoll
(
heading
,
pitch
,
roll
);
const
orientation
=
Cesium
.
Transforms
.
headingPitchRollQuaternion
(
position
,
hpr
);
let
cylinder_slices4_top0
=
viewer
.
entities
.
add
({
name
:
"cylinder_slices4_top0"
,
position
:
position
,
orientation
:
orientation
,
cylinder
:
{
length
:
1000000
,
topRadius
:
200.0
,
bottomRadius
:
200000.0
,
material
:
Cesium
.
Color
.
YELLOW
,
outline
:
true
,
outlineWidth
:
3.0
,
slices
:
4
,
},
});
// let lon = 27.13
// let lat = 22.92
// let xyz = Cesium.Cartesian3.fromDegrees(lon, lat)
// console.log(lon,lat)
// console.log(xyz)
})
</
script
>
<
style
>
.all
{
display
:
block
;
position
:
absolute
;
top
:
0
;
left
:
0
;
border
:
none
;
width
:
100%
;
height
:
100%
}
.cesium-viewer-bottom
{
display
:
none
;
}
button
{
position
:
absolute
;
top
:
50px
;
left
:
50px
;
z-index
:
88
;
}
</
style
>
src/encapsulation/point.vue
0 → 100644
View file @
cc0b55de
<
template
>
<div
id=
"cesiumContainer"
class=
"all"
></div>
<div
class=
"absolute top-2000 left-20"
>
<button
@
click=
"delete1"
>
删除
</button>
</div>
<button
@
click=
"update"
class=
"absolute top-20 left-2"
>
设置点的属性
</button>
</
template
>
<
script
setup
>
import
{
onMounted
}
from
'vue'
import
*
as
Cesium
from
'cesium'
import
Point
from
'/src/js/point.js'
let
entity
onMounted
(()
=>
{
Cesium
.
Ion
.
defaultAccessToken
=
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyYTI3MDQxMS1hYzgxLTRlYTQtODExZS00YzdmYjM0YTg3OTAiLCJpZCI6MjI0NzQzLCJpYXQiOjE3MTkzOTcxMDF9._VD-W1rEy7jSUtPmcVytEYbZIZ00_IeHCZm59Kua5aE'
const
viewer
=
new
Cesium
.
Viewer
(
"cesiumContainer"
,
{
})
var
start
=
new
Cesium
.
JulianDate
.
fromDate
(
new
Date
());
start
=
Cesium
.
JulianDate
.
addHours
(
start
,
8
,
new
Cesium
.
JulianDate
());
let
point
=
{
id
:
"point"
,
position
:
Cesium
.
Cartesian3
.
fromDegrees
(
-
70
,
30
),
alpha
:
0.3
,
name
:
'i am point'
,
nameSize
:
20
,
nameOffset
:
[
20
,
20
],
modelUrl
:
'/src/model/moon1.glb'
,
modelVisible
:
true
,
moduleScale
:
20000
,
}
entity
=
new
Point
(
viewer
,
point
)
console
.
log
(
entity
.
getPosition
(
start
))
})
function
delete1
()
{
entity
.
removeFromScene
()
}
function
update
()
{
let
point
=
{
position
:
{
longitude
:
-
80
,
latitude
:
30
,
height
:
1000
// 设置高度,如果需要的话
},
color
:
Cesium
.
Color
.
fromBytes
(
0
,
255
,
0
),
label
:
{
text
:
'Sample Label'
,
font
:
'16px Arial'
,
fillColor
:
'#FF0000'
,
// 红色
pixelOffset
:
{
x
:
10
,
y
:
20
}
}
}
entity
.
setProperty
(
point
)
}
</
script
>
<
style
>
.all
{
display
:
block
;
position
:
absolute
;
top
:
0
;
left
:
0
;
border
:
none
;
width
:
100%
;
height
:
100%
}
.cesium-viewer-bottom
{
display
:
none
;
}
button
{
position
:
absolute
;
top
:
50px
;
left
:
50px
;
z-index
:
88
;
}
</
style
>
src/js/point.js
0 → 100644
View file @
cc0b55de
import
*
as
Cesium
from
'cesium'
/**
* @class 基于Entity.Point封装的点
* @classdesc
*/
class
Point
{
/**
* 点的构造函数
* @param {Object} map - viewer对象
* @param {String} [id] - 点对象的ID
* @param {Array} [position] - 点的位置信息
* @param {Boolean} [visible=true] - 点的显隐性
* @param {String} [color='rgb(255,0,0)'] - 点的颜色
* @param {Number} [alpha=1.0] - 点的不透明度
* @param {String} [name='point'] - 点的名称
* @param {Boolean} [nameVisible=true] - 点名称的可见性
* @param {Number} [nameSize=14] - 点名称的大小
* @param {Array} [nameOffset=[10,0]] - 点名称的偏移
* @param {String} [modelUrl] - 模型地址
* @param {Boolean} [modelVisible=false] - 模型显隐性
* @param {Number} [modelScale=1] - 模型缩放尺寸
* @param {Number} [heading=0] - 方位角
* @param {Number} [pitch=0] - 俯仰角
* @param {Number} [roll=0] - 滚动角
* @param {String} [markUrl] - 标记模型地址
* @param {String} [markScale] - 标记大小
* @param {String} [markVisible] - 标记显隐性
*/
constructor
(
map
,
options
=
{})
{
const
viewer
=
map
this
.
entityCollection
=
viewer
.
entities
;
const
POINT
=
{
id
:
null
,
position
:
null
,
visible
:
true
,
pixelSize
:
10
,
color
:
Cesium
.
Color
.
fromBytes
(
255
,
0
,
0
),
alpha
:
1.0
,
name
:
'point'
,
nameVisible
:
true
,
nameSize
:
14
,
nameOffset
:
[
10
,
10
],
modelUrl
:
''
,
modelVisible
:
false
,
modelScale
:
1
,
heading
:
0
,
pitch
:
0
,
roll
:
0
,
markUrl
:
''
,
markScale
:
10
,
markVisible
:
false
,
};
const
finalOptions
=
{
...
POINT
,
...
options
};
const
{
position
,
id
,
...
pointOptions
}
=
finalOptions
;
this
.
entity
=
viewer
.
entities
.
add
({
id
:
id
,
position
:
position
,
point
:
pointOptions
.
visible
?
{
pixelSize
:
pointOptions
.
pixelSize
,
color
:
Cesium
.
Color
.
clone
(
pointOptions
.
color
).
withAlpha
(
pointOptions
.
alpha
)
}:
undefined
,
label
:
pointOptions
.
nameVisible
?
{
text
:
pointOptions
.
name
,
font
:
`
${
pointOptions
.
nameSize
}
px sans-serif`
,
fillColor
:
Cesium
.
Color
.
WHITE
,
pixelOffset
:
new
Cesium
.
Cartesian2
(...
pointOptions
.
nameOffset
),
}
:
undefined
,
model
:
pointOptions
.
modelVisible
?
{
uri
:
pointOptions
.
modelUrl
,
scale
:
pointOptions
.
modelScale
,
minimumPixelSize
:
640
,
maximumScale
:
20000
,
modelMatrix
:
Cesium
.
Transforms
.
headingPitchRollToFixedFrame
(
position
,
new
Cesium
.
HeadingPitchRoll
(
Cesium
.
Math
.
toRadians
(
pointOptions
.
heading
),
Cesium
.
Math
.
toRadians
(
pointOptions
.
pitch
),
Cesium
.
Math
.
toRadians
(
pointOptions
.
roll
)
)
),
}
:
undefined
,
billboard
:
pointOptions
.
markVisible
?
{
image
:
pointOptions
.
markUrl
,
scale
:
pointOptions
.
markScale
}
:
undefined
});
}
/**
* 获取查询时刻点所在位置
* @param {Cesium.JulianDate} time 查询时刻
* @returns {Cesium.Cartesian3} 点的位置
*/
getPosition
(
time
)
{
if
(
!
this
.
entity
||
!
this
.
entity
.
position
)
{
throw
new
Error
(
'点实体或位置未定义'
);
}
const
position
=
this
.
entity
.
position
.
getValue
(
time
);
return
position
;
}
/**
* 设置点的属性
* @param {Object} options 点的属性
*/
setProperty
(
options
)
{
if
(
!
this
.
entity
)
{
throw
new
Error
(
'点实体未定义'
);
}
if
(
options
.
position
)
{
this
.
entity
.
position
=
Cesium
.
Cartesian3
.
fromDegrees
(
options
.
position
.
longitude
,
options
.
position
.
latitude
,
options
.
position
.
height
||
0
);
}
if
(
options
.
color
)
{
this
.
entity
.
point
.
color
=
options
.
color
;
}
if
(
options
.
label
)
{
this
.
entity
.
label
=
new
Cesium
.
LabelGraphics
({
text
:
options
.
label
.
text
||
''
,
// 默认为空字符串
font
:
options
.
label
.
font
||
'14px sans-serif'
,
// 默认字体
fillColor
:
Cesium
.
Color
.
fromCssColorString
(
options
.
label
.
fillColor
||
'#FFFFFF'
),
// 默认白色
pixelOffset
:
new
Cesium
.
Cartesian2
(
options
.
label
.
pixelOffset
?
options
.
label
.
pixelOffset
.
x
:
0
,
options
.
label
.
pixelOffset
?
options
.
label
.
pixelOffset
.
y
:
0
)
});
}
}
/**
* 从场景中移除点
*/
removeFromScene
()
{
if
(
!
this
.
entity
)
{
throw
new
Error
(
'点实体未定义'
);
}
this
.
entityCollection
.
remove
(
this
.
entity
);
this
.
entity
=
null
;
}
}
export
default
Point
;
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment