public Expectation(Name expectedName, LeafIndex expectedLeafIndex) { Contract.Requires(expectedName != null); ExpectedName = expectedName; ExpectedLeafIndex = expectedLeafIndex; }
public ParsedElement(NotationFormIndex notationOccurenceIndex, ParseParsedIndex parsingIndex, LeafIndex start, LeafIndex end) { this.NotationIndex = notationOccurenceIndex; this.ParseIndex = parsingIndex; this.Start = start; this.End = end; }
private LeafIndex GetLeafIndex(Mesh mesh, BranchIndex fromBranchIndex, GameObjectInfo objectInfo) { LeafIndex index = new LeafIndex(); /* * 存储信息: * 索引值和器官类型 * 用于后续判断不同时期的两个器官索引是否为相同索引 */ index.Index = GetIndexWithSameType(OrganType.Leaf, fromBranchIndex); index.LeafMesh = mesh; /* * 存储空间信息: * 半径、旋转方向 * 用于后续绘制 */ index.Radius = objectInfo.Radius; index.Rotation = objectInfo.Rotation; /* * 存储上下文信息: * 从属枝干 */ index.From = fromBranchIndex; /* * 病虫害信息: * 细胞纹理 */ index.CelluarTex = CellularTexMemory.GetInstance().GetCellularTex(0); return(index); }
private void LeafMorphologicalInheritance() { OrganMorphologicalInheritance(); //基类中的数据继承 LeafIndex curLeafIndex = CurIndex as LeafIndex; LeafIndex preLeafIndex = PreIndex as LeafIndex; curLeafIndex.Width = preLeafIndex.Width; curLeafIndex.LeafArea = preLeafIndex.LeafArea; curLeafIndex.LeafArea_Uninsected = preLeafIndex.LeafArea_Uninsected; curLeafIndex.LimitRatio = preLeafIndex.LimitRatio; curLeafIndex.Texture_PreDay = GameObjectOperation.GetTexture(preLeafIndex.Belong); curLeafIndex.MeshHashCode_PreDay = preLeafIndex.LeafMesh.GetHashCode(); }
/// <summary> /// 模拟天空直射 /// </summary> /// <param name="SolarDayAngle_Rad">太阳日角</param> /// <param name="SolarAltitude_Deg">太阳高度角</param> /// <param name="SolarAzimuth_Deg">太阳方位角</param> /// <param name="StartHour">开始的时间</param> /// <param name="EndHour">结束时间</param> /// <param name="_Octree">八叉树</param> /// <param name="d">光线之间的间隔,即光线密度</param> public static void DirectionLightSimulation(double SolarDayAngle_Rad, double SolarAltitude_Deg, double SolarAzimuth_Deg, double StartHour, double EndHour, Octree _Octree, float d) { Light[] Lights = DirectLights(SolarDayAngle_Rad, SolarAltitude_Deg, SolarAzimuth_Deg, _Octree, d); //获取所有直射光线 foreach (Light _Light in Lights) { Triangle HitTriangle; if (!RayTracing.CollisionDection(_Light, _Octree, out HitTriangle)) { continue; //如果该光线没有与三角面片相交,则遍历下一条光线 } if (HitTriangle.Type != OrganType.Leaf) { continue; //如果相交三角面片不为叶子,则遍历下一条光线 } LeafIndex _LeafIndex = HitTriangle.Index as LeafIndex; _LeafIndex.DirectionEnergy += _Light.Energy; //累加叶子的直射能量 } }
/// <summary> /// 模拟天空散射 /// </summary> /// <param name="SolarDayAngle_Deg">太阳日角</param> /// <param name="SolarAltitude_Deg">太阳高度角</param> /// <param name="StartHour">开始的时间</param> /// <param name="EndHour">结束的时间</param> /// <param name="_Octree">八叉树</param> /// <param name="LatitudeNum">纬度方向的剖分个数</param> /// <param name="LongtitudeNum">经度度方向的剖分个数</param> public static void ScatterLightSimulation(TreeModel treeModel, double SolarDayAngle_Rad, double SolarAltitude_Deg, double StartHour, double EndHour, Octree _Octree, int LatitudeNum, int LongtitudeNum) { Triangle[] TreeTriangles = GameObjectOperation.GetTreeTriangles(treeModel).ToArray(); //获取所有的三角面片 double _ScatterIrradiance = ScatterIrradiance(SolarDayAngle_Rad, SolarAltitude_Deg, _Octree.Root.Bounds.center.y); //总散射辐射度 LightCastHemisphere LightHemisphere = null; for (int i = 0; i < TreeTriangles.Length; i++) { if (TreeTriangles[i].Type != OrganType.Leaf) { continue; //非叶片,无需计算散射辐射 } /* * 优化 * 限定天穹半球的大小 * 每次三角面片,天穹半球跟随三角面片移动,无需重新计算 */ if (LightHemisphere == null) { LightHemisphere = new LightCastHemisphere(TreeTriangles[i].Center, _Octree.Root.Bounds); } else { LightHemisphere.MoveTo(TreeTriangles[i].Center); } /* * 通过天穹半球计算出天空散射透过率 * 该面片上的平均散射辐射度(W / m^2) = 天空散射透过率 * 总散射辐射度 * 该面片上的总辐射度(W) = 平均散射辐射度 * 该面片的面积 * 注意:因为存在透明的纹理,因此需要再得到整个叶片模型的散射能量的基础上,再乘以非透明的比例,才能得到真正的散射能量 */ LeafIndex _LeafIndex = TreeTriangles[i].Index as LeafIndex; _LeafIndex.ModelScatterEnergy += (float)(LightHemisphere.GetSkyTransmissivity(LongtitudeNum, LatitudeNum, TreeTriangles, i) * _ScatterIrradiance * TreeTriangles[i].Area()); } }
/// <summary> /// 获取一定时间内平均PAR值(umol/(s * m^2)) /// </summary> /// <param name="leafArea">叶片面积</param> public static double PARRecption_Mean(TreeModel treeModel, out double leafArea) { List <OrganIndex> organIndexes = treeModel.OrganIndexes; double energy = 0; leafArea = 0; foreach (OrganIndex organIndex in organIndexes) { if (organIndex.Type != OrganType.Leaf) { continue; //非叶片索引 } LeafIndex leafIndex = organIndex as LeafIndex; energy += leafIndex.TotalEnergy; //辐射能量累加(单位 W) leafArea += leafIndex.LeafArea; //叶面积累加(单位 ㎡) } double radiation = energy / leafArea; //辐照度(单位 W * m^-2) return(SolarSim.IrradianceToPPFD(radiation)); }
public NameBinding(Name name, LeafIndex indexOfMatched, NameInstance matchedNameInstance) { this.Index = indexOfMatched; this.Name = name; this.Instance = matchedNameInstance; }
/// <summary> /// 获取一定时间内单个叶片的PAR值(umol/(s * m^2)) /// </summary> public static double PARRecption(LeafIndex index) { return(SolarSim.IrradianceToPPFD(index.TotalEnergy / index.LeafArea)); }
private void CreateLeafModel(LeafIndex index, Vector3 position) { /* * 计算形态数据:长度和最大宽度 * 用于后续生成GameObject */ index.MorphologicalSim(); GameObject leafModel = (GameObject)GameObject.Instantiate(index.LeafMesh.Instance); //模型实例化 leafModel.name = index.LeafMesh.Name; leafModel.tag = "Organ"; SetTagInParent(leafModel.transform, "Organ"); /* * 设置空间信息 */ leafModel.transform.position = position; RotationGameObject(leafModel, position, index.Rotation); /* * 养分 */ List <Material> materials = GameObjectOperation.GetMaterials(leafModel); switch (EnvironmentParams.NutrientType) { case LightResponseType.N_LACK: //SetIllnessColor(materials, MaizeParams.lackN_Color); break; case LightResponseType.P_LACK: SetIllnessColor(materials, MaizeParams.lackP_Color); break; case LightResponseType.K_LACK: SetIllnessColor(materials, MaizeParams.lackK_Color); break; } /* * 设置形态信息 * 受病虫害影响后,叶面积变化较大 * 而整体比例影响较小 * 故采用未受到病虫害影响的叶面积计算比例 */ float scale = Mathf.Sqrt((float)(index.LeafArea_Uninsected / index.UniformLeafArea)); leafModel.transform.localScale = Vector3.one * scale; /* * 设置父节点 */ leafModel.transform.SetParent(BranchModel.transform); /* * 信息补齐 */ index.Belong = leafModel; m_listOrganModels.Add(leafModel); }
public void MorphologicalSim(double biomass, bool isClear = true, bool isSameGC = false) { DataCheck(); //数据检查 /* * 包含枝干和器官的索引 * 其每一个索引包含了后续生成GameObject所需的形态信息(旋转角度)以及 * 生成形态信息所需的数据(生物量、年龄) */ List <OrganIndex> indexes = GetIndexes(isClear, isSameGC); /* * 分配生物量给各个器官 * 累积的生物量为后续形态模拟提供参考依据 */ FunctionSim.PhotosynthateAllocation(this, biomass, FunctionSim.GrowthPeriodJudgment(BranchIndexes, OrganIndexes)); /* * 遍历每个Index * 计算形态数据 * 根据形态数据绘制GameObject */ int curLevel = 0; Vector3 curPosition = Vector3.zero; Stack <Vector3> positionStack = new Stack <Vector3>(); foreach (OrganIndex index in indexes) { switch (index.Type) { case OrganType.Branch: BranchIndex branchIndex = index as BranchIndex; if (branchIndex.Level > curLevel) { positionStack.Push(curPosition); } else if (branchIndex.Level < curLevel) { curPosition = positionStack.Pop(); } curLevel = branchIndex.Level; curPosition = RecordBranchModel(branchIndex, curPosition); break; case OrganType.Leaf: LeafIndex leafIndex = index as LeafIndex; CreateLeafModel(leafIndex, curPosition); break; case OrganType.Flower: MaleIndex maleIndex = index as MaleIndex; CreateFlowerModel(maleIndex, curPosition); break; case OrganType.Fruit: FemaleIndex femaleIndex = index as FemaleIndex; CreateFruitModel(femaleIndex, curPosition); break; } } CreateBranchModel(); /* * 病虫害模拟 * 测试 */ InsectSimulation(); PostProcessing(); }