搜索在C#中操作xml可找到很多相关教程,此处就不细说了。krpano的全景xml文件和传统xml文件的不同仅在于它们的根不一样,vtour.xml文件的根为:

<krpano version="1.19" title="">
</krpano>

  每个全景一般都包含有include、skin_settings、action这三个子元素,之后才是场景scene,scene里有自己的属性,还有view、hotspot等子元素。
  还需要明确的是,每个场景都一一个唯一名称,原始名称为图片名(没有后缀),在xml文件里,name指示这个唯一名称,在panos瓦片文件夹里,每个场景瓦片的文件夹名则为这个唯一名称,加入全景照片为123.jpg,则:

//场景名称,唯一
//注意如果不要scene,则场景名称不能以数字开头,但如果去掉scene,则很多地方也要跟着修改(同样,热点名称也不能以数字开头)
name="scene_123"
//在浏览场景时显示的名称,可以修改
title="123"
//瓦片文件夹名称,后面会加上.tiles
“123.tiles”

  下面来看具体的操作:

在进行操作前要引用命名空间

using System.Xml;

加载xml文件及保存

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(xmlpath); //xml绝对路径 加载xml文件RenameScene(xmlDoc, "name1", "title1"); //修改title
MoveScene(xmlDoc, ["name1", "name2"]); //更改场景顺序
DeleteScene(xmlDoc, "name1"); //删除场景
RaiseScene(xmlDoc, ["name1", "name2"], "raisename", "after"); //添加场景
ReplaceScene(xmlDoc, ["name1", "name2"]); //替换场景
SetView(xmlDoc, "name1", "10", "20.5"); //设置进入场景时的初始视角xmlDoc.Save(xmlpath); //保存xml文件

修改场景显示名称:操作xml文件

/// <summary>
/// 修改场景显示名称title
/// </summary>
/// <param name="xmlDoc">xml文件</param>
/// <param name="sceneid">场景唯一名称name</param>
/// <param name="scenename">scenename</param>
/// <returns>成功/失败</returns>
private string RenameScene(XmlDocument xmlDoc, string sceneid, string scenename)
{try{XmlNode renameNode = xmlDoc.DocumentElement.SelectSingleNode("/krpano/scene[@name='scene_" + sceneid + "']");XmlElement element = (XmlElement)renameNode;element.SetAttribute("title", scenename);return "success";}catch (Exception ex){return "failed";}
}

更换场景顺序:操作xml文件

/// <summary>
/// 更换场景顺序:根据新顺序将要排放的场景结点放到栈或者队列中,然后重新排位置,注意栈和队列的出入顺序
/// </summary>
/// <param name="xmlDoc">xml文件</param>
/// <param name="sceneid">按新顺序排列的场景名称</param>
/// <returns>成功/失败</returns>
public string MoveScene(XmlDocument xmlDoc, string[] sceneid)
{try{XmlNode rootNode = xmlDoc.SelectSingleNode("/krpano/action").ParentNode;Stack<XmlNode> tourNode = new Stack<XmlNode>();for (int len=sceneid.Length, i = len - 1; i > -1; i--){XmlNode moveNode = xmlDoc.DocumentElement.SelectSingleNode("/krpano/scene[@name='scene_" + sceneid[i] + "']");tourNode.Push(moveNode);rootNode.RemoveChild(moveNode);}while (tourNode.Count() > 0){rootNode.AppendChild(tourNode.Pop());}return "success";}catch (Exception ex){return "failed";}
}

删除场景:操作xml文件、panos/*.tiles文件夹

/// <summary>
/// 删除场景
/// </summary>
/// <param name="xmlDoc">xml文件</param>
/// <param name="sceneid">场景名称</param>
/// <returns>成功/失败</returns>
public string DeleteScene(XmlDocument xmlDoc, string sceneid)
{try{XmlNode selectNode = xmlDoc.SelectSingleNode("/krpano/scene[@name='scene_" + sceneid + "']");selectNode.ParentNode.RemoveChild(selectNode);//删除场景对应的瓦片图片文件夹,注意路径//后面有“true”,表示删除这个文件夹及其子目录Directory.Delete("../panos/" + sceneid + ".tiles", true);return "success";}catch (Exception ex){return "failed";}
}

添加场景:操作xml文件、panos/*.tiles文件夹

/// <summary>
/// 添加场景:把其他全景里的一些场景添加到这个场景中来
/// </summary>
/// <param name="xmlDoc">xml文件</param>
/// <param name="sceneid">要添加的场景的名称</param>
/// <param name="sceneseat">参考位置的场景名称:要添加在这个场景前后</param>
/// <param name="sceneab">before/after添加在参考位置的前面或者后面</param>
/// <returns>成功/失败</returns>
public string RaiseScene(XmlDocument xmlDoc, string[] sceneid, string sceneseat, string sceneab)
{int len = sceneid.Length//被添加场景所在的xml文件XmlDocument xmlDoc_move = new XmlDocument();xmlDoc_move.Load(xml_movepath);try{//移动场景对应的瓦片图片文件夹//此处我移动新全景里所有文件,如果只是特定场景可以根据场景名称找到对应瓦片然后移动int count = Directory.GetDirectories("../panos").Length;List<string> folders = new List<string>(Directory.GetDirectories("../panos"));for (int i = 0; i < count; i++){string realtile = "../panos/" + Path.GetFileName(folders[i]);if (!Directory.Exists(realtile))Directory.Move(folders[i], realtile);elsereturn;}//添加其实是将场景结点从一个xml文件移动到另一个xml文件//由于栈的出入规定,这个地方不用栈用链表要更容易懂些Stack<XmlNode> tourNode = new Stack<XmlNode>();for (int i = len - 1; i > -1; i++){//如果场景在原xml中不是按顺序排列,则用第一句,按场景name添加进栈//如果场景在原xml中按顺序排列,则可用第二句,直接按顺序添加tourNode.Push(xmlDoc_move.DocumentElement.SelectSingleNode("/krpano/scene[@name='scene_" + sceneid[i] + "']");tourNode.Push(xmlDoc_move.DocumentElement.SelectSingleNode("/krpano/scene[last()-" + i + "]"));}//直接加在xml文件末尾,目前顺序为倒序添加,如果是正序,则上面的循环要从i=0开始while (len > 0){//从其他xml文件引用结点要用import,类似的从一个datatable引用行列到另一个datatable也要用DataTable.ImportRow()等XmlNode markNode = xmlDoc.ImportNode(tourNode.Pop(), true);xmlDoc.DocumentElement.AppendChild(markNode);len--;}//添加在指定场景的前面或者后面,按原始顺序排列XmlNode rootNode = xmlDoc.SelectSingleNode("/krpano/action").ParentNode;XmlNode seatNode = xmlDoc.DocumentElement.SelectSingleNode("/krpano/scene[@name='scene_" + sceneseat + "']");if (sceneab == "before"){while (tourNode.Count() > 0){XmlNode markNode = xmlDoc.ImportNode(tourNode.Pop(), true);rootNode.InsertBefore(markNode, seatNode);}}else{while (tourNode.Count() > 0){XmlNode markNode = xmlDoc.ImportNode(tourNode.Pop(), true);rootNode.InsertAfter(markNode, seatNode);}}return "success";}catch (Exception ex){return "failed";}
}

替换场景:操作xml文件、panos/*.tiles文件夹

/// <summary>
/// 替换场景
/// </summary>
/// <param name="xmlDoc">xml文件</param>
/// <param name="sceneid">被替换的场景的名称</param>
/// <returns>成功/失败</returns>
public string ReplaceScene(XmlDocument xmlDoc, string[] sceneid)
{int len = sceneid.Length//被添加场景所在的xml文件XmlDocument xmlDoc_move = new XmlDocument();xmlDoc_move.Load(xml_movepath);try{Stack<XmlNode> tourNode = new Stack<XmlNode>();XmlNode rootNode = xmlDoc.SelectSingleNode("/krpano/action").ParentNode;//用其他xml文件里的场景替换当前xml文件中的场景for (int i = len - 1; i > -1; i++){//如果场景在原xml中不是按顺序排列,则用第一句,按场景name添加进栈//如果场景在原xml中按顺序排列,则可用第二句,直接按顺序添加//注意场景入栈顺序应和sceneid内被替换顺序的反序一一对应,也即出栈顺序和sceneid顺序一一对应tourNode.Push(xmlDoc_move.DocumentElement.SelectSingleNode("/krpano/scene[@name='scene_" + sceneid[i] + "']");tourNode.Push(xmlDoc_move.DocumentElement.SelectSingleNode("/krpano/scene[last()-" + i + "]"));}for (int i = 0; i < len; i++){XmlNode markNode = xmlDoc.ImportNode(tourNode.Pop(), true);rootNode.ReplaceChild(markNode, xmlDoc.DocumentElement.SelectSingleNode("/krpano/scene[@name='scene_" + sceneid[i] + "']"));                    }//移动替换场景瓦片,删除被替换场景瓦片int count = Directory.GetDirectories("../panos").Length;List<string> folders = new List<string>(Directory.GetDirectories("../panos"));for (int i = 0; i < count; i++){string realtile = "../panos/" + Path.GetFileName(folders[i]);if (!Directory.Exists(realtile))Directory.Move(folders[i], realtile);elsereturn;}for (int i = 0; i < len; i++){Directory.Delete("../panos/" + sceneid[i] + ".tiles", true); }//同一个xml文件里场景替换for (int i = 0; i < len; i++){//假设替换场景为最后的几个场景,如果是特定场景用SelectSingleNode选定XmlNode moveNode = rootNode.LastChild;XmlElement element = (XmlElement)moveNode;tourNode.Push(moveNode);rootNode.RemoveChild(moveNode);}for (int i = 0; i < len; i++){rootNode.ReplaceChild(tourNode.Pop(), xmlDoc.DocumentElement.SelectSingleNode("/krpano/scene[@name='scene_" + array[i] + "']"));Directory.Delete("../panos/" + sceneid[i] + ".tiles", true); }return "success";}catch (Exception ex){return "failed";}
}

设置场景初始视角:操作xml文件

/// <summary>
/// 设置场景初始视角
/// </summary>
/// <param name="markid">markid</param>
/// <param name="sceneid">sceneid</param>
/// <param name="viewhlookat">viewhlookat</param>
/// <param name="viewvlookat">viewvlookat</param>
/// <returns>成功/失败</returns>
public string SetView(XmlDocument xmlDoc, string sceneid, string viewhlookat, string viewvlookat)
{try{XmlNode reviseNode = xmlDoc.DocumentElement.SelectSingleNode("/krpano/scene[@name='" + sceneid + "']").FirstChild;XmlElement element = (XmlElement)reviseNode;element.SetAttribute("hlookat", viewhlookat);element.SetAttribute("vlookat", viewvlookat);xmlDoc.Save(markidxmlpath);return "success";}catch (Exception ex){return "failed";}
}

附录:用两张全景照片在MAKE VTOUR (NORMAL) droplet.bat上生成全景的xml文件

<krpano version="1.19" title="Virtual Tour"><include url="skin/vtourskin.xml" /><!-- customize skin settings: maps, gyro, webvr, thumbnails, tooltips, layout, design, ... --><skin_settings maps="false"maps_type="google"maps_bing_api_key=""maps_google_api_key=""maps_zoombuttons="false"gyro="true"webvr="true"webvr_gyro_keeplookingdirection="false"webvr_prev_next_hotspots="true"littleplanetintro="false"title="true"thumbs="true"thumbs_width="120" thumbs_height="80" thumbs_padding="10" thumbs_crop="0|40|240|160"thumbs_opened="false"thumbs_text="false"thumbs_dragging="true"thumbs_onhoverscrolling="false"thumbs_scrollbuttons="false"thumbs_scrollindicator="false"thumbs_loop="false"tooltips_buttons="false"tooltips_thumbs="false"tooltips_hotspots="false"tooltips_mapspots="false"deeplinking="false"loadscene_flags="MERGE"loadscene_blend="OPENBLEND(0.5, 0.0, 0.75, 0.05, linear)"loadscene_blend_prev="SLIDEBLEND(0.5, 180, 0.75, linear)"loadscene_blend_next="SLIDEBLEND(0.5,   0, 0.75, linear)"loadingtext="loading..."layout_width="100%"layout_maxwidth="814"controlbar_width="-24"controlbar_height="40"controlbar_offset="20"controlbar_offset_closed="-40"controlbar_overlap.no-fractionalscaling="10"controlbar_overlap.fractionalscaling="0"design_skin_images="vtourskin.png"design_bgcolor="0x2D3E50"design_bgalpha="0.8"design_bgborder="0"design_bgroundedge="1"design_bgshadow="0 4 10 0x000000 0.3"design_thumbborder_bgborder="3 0xFFFFFF 1.0"design_thumbborder_padding="2"design_thumbborder_bgroundedge="0"design_text_css="color:#FFFFFF; font-family:Arial;"design_text_shadow="1"/><!-- startup action - load the first scene --><action name="startup" autorun="onstart">if(startscene === null OR !scene[get(startscene)], copy(startscene,scene[0].name); );loadscene(get(startscene), null, MERGE);if(startactions !== null, startactions() );</action><scene name="scene_Ghm1_color" title="Ghm1_color" onstart="" thumburl="panos/Ghm1_color.tiles/thumb.jpg" lat="" lng="" heading=""><view hlookat="0" vlookat="0" fovtype="MFOV" fov="120" maxpixelzoom="2.0" fovmin="70" fovmax="140" limitview="range" vlookatmin="-54.349" vlookatmax="54.349" /><preview url="panos/Ghm1_color.tiles/preview.jpg" /><image><cube url="panos/Ghm1_color.tiles/pano_%s.jpg" /><cube url="panos/Ghm1_color.tiles/mobile/pano_%s.jpg" devices="mobile" /></image><!-- place your scene hotspots here --></scene><scene name="scene_Ghm2_color" title="Ghm2_color" onstart="" thumburl="panos/Ghm2_color.tiles/thumb.jpg" lat="" lng="" heading=""><view hlookat="0" vlookat="0" fovtype="MFOV" fov="120" maxpixelzoom="2.0" fovmin="70" fovmax="140" limitview="range" vlookatmin="-54.349" vlookatmax="54.349" /><preview url="panos/Ghm2_color.tiles/preview.jpg" /><image><cube url="panos/Ghm2_color.tiles/pano_%s.jpg" /><cube url="panos/Ghm2_color.tiles/mobile/pano_%s.jpg" devices="mobile" /></image><!-- place your scene hotspots here --></scene>
</krpano>

Krpano学习:在C#中修改全景场景属性(C#操作全景vtour.xml文件及相关瓦片数据/panos/*.tiles)相关推荐

  1. NS2相关学习——在ns中模拟无线场景

    之前学习的都是有线场景下的NS2相关应用,现在开始,终于要学习无线啦!无线是我研究的重点,要好好学习呀! 在本节中,我们将学习使用ns中提供的移动无线仿真模型. 该部分由两部分组成. 在第一小节中,我 ...

  2. oracle中修改多个字段默认值_利用VBA代码在已有的数据表中删除、添加、修改字段...

    大家好,今日继续给大家讲解VBA数据库解决方案的第21讲,如何利用VBA代码在已有的数据表中删除,添加,修改字段.这个内容是操作数据库的一项必修的内容,还望大家在实际工作中多利用,所以这节的知识,对于 ...

  3. VTK学习笔记3:IO操作读取写入xml文件和vtk文件

    1.vtu文件 vtk实战(二十四)--读入vtu数据 vtk实战(三十)--写入vtu数据 2.vtp文件 2.1读入vtp文件 2.2 创建vtp文件 从网络示例和在线文档中,我收集了一些信息,创 ...

  4. c#语言 修改xml文件路径,C#对XML操作:编辑XML文件内容-.NET教程,C#语言

    public void page_load(object src,eventargs e) { /* * 版 权 : copyright by sem it department * 版 本 : ve ...

  5. WPF拖拽过程中修改鼠标指针属性

    在WPF中鼠标拖拽时,指针默认是个圆圈(呵呵,有点难看),网上找了一圈没有找到好的方法,在此把我的解决过程写下: 在拖拽过程中使用到了DragDrop类,类中DoDragDrop方法为启动拖拽操作,而 ...

  6. 如何修改was的java路径_在eclipse中修改tomcat的部署路径操作

    在eclipse上面部署web项目后,它没有将你的项目文件放到tomcat 的目录下面.而是放在了你的工作目录下面. 你到这里去找:E:\jintao\.metadata\.plugins\org.e ...

  7. 在LinearLayout中嵌套RelativeLayout来设置Button的位置(xml文件)

    想将Button和ListView分别放在屏幕的一左一右. 单纯使用android:gravity和android:layout_gravity不成功. 于是涉及到RelativeLayout 关键为 ...

  8. Spring中注入List,Set,Map,Properties的xml文件配置方法

    下面的例子展示了如何注入 List – <list/> Set – <set/> Map – <map/> Properties – <props/> ...

  9. mysql修改表名几种方式_Oracle数据库中修改表名的几种方式

    Oracle数据库中修改表名的几种方式如下:answer1: ALTER TABLE old_table_name RENAME TO new_table_name;(大写为系统命令)answer2: ...

  10. Spring Cloud Alibaba基础教程:Sentinel Dashboard中修改规则同步到Apollo

    在之前的两篇教程中我们分别介绍了如何将Sentinel的限流规则存储到Nacos和Apollo中.同时,在文末的思考中,我都指出了这两套整合方案都存在一个不足之处:不论采用什么配置中心,限流规则都只能 ...

最新文章

  1. 有哪些堪称神器的实用网站?这8个可以解你燃眉之急!
  2. 2011 年最重要的 10 个开源软件
  3. LeoFS —— 高可靠性的分布式对象存储系统
  4. SpringMVC系列(二): SpringMVC各个注解的使用
  5. [php-src]扩展中封装业务与 call_user_function 的使用建议
  6. 用软件lm_sensors监测Linux系统和CPU温度(转)
  7. SDK 和 API
  8. mapreduce 算法_MapReduce算法–了解数据联接第1部分
  9. 信息学奥赛一本通(1050:骑车与走路)
  10. python装饰器详解51-python装饰器使用实例详解
  11. 关于Dijkstra最短路径算法
  12. mysql+读的负载均衡_MySQL Proxy快速实现读写分离以及负载均衡
  13. 等到小牛电动车出N2再买的原因
  14. springMVC使用HandlerMethodArgumentResolver 自定义解析器实现请求参数绑定方法参数
  15. vue3如何去掉控制台的warn信息
  16. 正海转债,寿22转债,东材转债上市价格预测
  17. Loadrunner11在Win10上使用踩过的坑
  18. 麒麟子Cocos Creator 3D研究笔记十:【qfw】开源的Extension Pack for Cocos Creator 3D
  19. 搭建自己的dns服务器
  20. ORACLE认证(OCM)介绍

热门文章

  1. 2021年安全员-B证(陕西省)考试报名及安全员-B证(陕西省)考试平台
  2. 冬天虽冷,希望你们能够坚强一点
  3. 【每周一文】关于淘宝首页的一段代码
  4. 让文字沿着路径动起来 (SVG)
  5. 亭亭玉立 三星SGH-E570俄罗斯上市
  6. [转]机器学习工具:scikit-learn/Weka
  7. Android--RelativeLayout相对布局
  8. 关于python turtle的函数的全部理解(尤其是绝对角度,90%的人会误解)
  9. [独有源码]springboot医养结合养老APP的设计与实现a7rv0借鉴他人经验,找到适合自己的毕业设计
  10. Pytorch中分类loss总结