cesium公交車軌跡漫游

個人博客:CSDN 博客-滿分觀察網友 z

演示地址:嗶哩嗶哩-滿分觀察網友 z

這是一個用 Cesium.js 做的公交車軌跡漫游,實現的功能有加載站點和道路軌跡點數據、監聽車輛的實時位置、車輛控制器。滾動屏等等。

文章目錄

  • 1. 地圖初始化
  • 2. 數據渲染
    • 2.1. 軌跡點
    • 2.2. 車牌
    • 2.3. 站牌標注
  • 3. 計算時間
    • 3.1. 時間總和
    • 3.2. 系統時間賦值
    • 3.3. 采樣位置
    • 3.4. 加載公交車
    • 3.5. 氣泡窗跟隨
  • 4. 面板展示
    • 4.1. 起點與目的地
    • 4.2. 站牌名字
    • 4.3. 車輛控制器
    • 4.4. 視角切換
    • 4.5. 后端數據模擬
    • 4.6. 調整速度
    • 4.7. 滾動屏
  • 5. 事件監聽器
  • 6. 移除事件

1. 地圖初始化

加載高德地圖。

const layer = new Cesium.UrlTemplateImageryProvider({url: "http://webrd02.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}",minimumLevel: 4,maximumLevel: 18,
});

對高德地圖進行濾色處理。

onMounted(() => {// viewer是操控地圖api的開始viewer = new Cesium.Viewer("cesiumContainer", {imageryProvider: layer,baseLayerPicker: false, //是否顯示圖層控件animation: false, //是否顯示動畫控件timeline: false, //是否顯示時間軸控件fullscreenButton: false, //是否顯示全屏控件geocoder: false, //是否顯示搜索控件homeButton: false, //是否顯示主頁按鈕navigationHelpButton: false, //是否顯示幫助提示按鈕sceneModePicker: false, //是否顯示投影方式控件shouldAnimate: true, // 是否自動播放selectionIndicator: false, //隱藏選中框infoBox: false, //隱藏右上角信息框shadows: true,});// 設置濾色modifyMap(viewer, {invertColor: true,filterRGB: [70, 110, 120],});initData();
});

image-20240702224531955

load.json 道路數據分析

image-20240702224752939

front_name:公交站起點

terminal_name:公交站終點

xs,ys:是軌跡點的坐標經緯度,需要進行處理

start_time:開始時間

end_time:結束時間

length:路程(公里)

stations:每個站點

  • name:站點的名字
  • xy_coords:站點的坐標

2. 數據渲染

2.1. 軌跡點

首先處理每個軌跡點的坐標,它們的經緯度坐標分開,需要拼接起來,使用 forEach 循環進行拼接,這里只需要循環一次即可,因為經度和緯度的坐標數組都是一樣長的,另一個可以根據循環的索引獲得。再將經緯度坐標轉為笛卡爾坐標,最后推入一個數組中保存。

let xArr = loadData.xs.split(",");
let yArr = loadData.ys.split(",");
xArr.forEach((item, index) => {positions.push(Cesium.Cartesian3.fromDegrees(Number(item), Number(yArr[index])));xyArr.push([Number(item), Number(yArr[index])]);
});

將軌跡點數據渲染到頁面上。

const line = viewer.entities.add({polyline: {positions,width: 10,material: Cesium.Color.WHITE.withAlpha(0.8),clampGround: true,},
});

2.2. 車牌

處理每個車牌的數據,先遍歷 loadData.stations,再獲得里面 xy_coords 數據,處理完后轉為笛卡爾坐標

// 獲得站牌坐標 并轉為笛卡爾坐標
let position = Cesium.Cartesian3.fromDegrees(...item.xy_coords.split(";").map((a) => Number(a))
);

加載對應的模型,,并改變站牌的大小和方向,進來的時候可以對著我們。

viewer.entities.add({position,orientation,model: {uri: "/src/assets/model.gltf",scale: 0.07,minimumPixelSize: 10,},
});
// 公交車牌的朝向
let orientation = Cesium.Transforms.headingPitchRollQuaternion(position,Cesium.HeadingPitchRoll.fromDegrees(90, 0, 0)
);

2.3. 站牌標注

展示站牌的標注,它的坐標跟站牌一樣,但是高度卻不一樣,需要額外進行處理。

let positionLabel = Cesium.Cartesian3.fromDegrees(...item.xy_coords.split(";").map((a) => Number(a)),24
);

添加站牌標注到地圖上。

viewer.entities.add({position: positionLabel,id: "label" + index,label: {text: item.name,font: "10px Helvetica",style: Cesium.LabelStyle.FILL_AND_OUTLINE,fillColor: Cesium.Color.WHITE, //字體顏色backgroundColor: Cesium.Color.BLACK.withAlpha(0.5), //背景顏色showBackground: true, //是否顯示背景顏色},
});

image-20240702230605739

3. 計算時間

獲得開始的時間和結束時間,開始時間可以隨便給,根據公式 s=vt,s 保持不變,v 可以自己設定,這樣就可以計算得到結束的時間了。

3.1. 時間總和

這里封裝一個數據來計算時間總數和每個軌跡點對應的系統時間,它接受兩個參數:pArr(軌跡點數組)和 speed(速度)。函數的實現原理是計算軌跡點之間的距離,利用 Cesium 自帶的distance計算,并將這些距離除以速度以得到每個軌跡點所對應的時間。最后,函數返回一個包含時間總和每個軌跡點對應的系統時間。

const getSiteTimes = (pArr, speed) => {let timeSum = 0,times = []; //timeSum花費時間總和,每一個軌跡點對應的時間for (let i = 0; i < pArr.length; i++) {if (i == 0) {times.push(0);continue;}// 計算時間總數timeSum += spaceDistance(pArr[i - 1], pArr[i]) / speed;// 每個軌跡點所對應的系統時間times.push(timeSum);}return { timeSum: timeSum, siteTime: times };
};// 計算兩點的距離
const spaceDistance = (a, b) => {return Cesium.Cartesian3.distance(a, b).toFixed(2);
};

設置速度為 20,可以獲得時間總和每個軌跡點對應的系統時間。

image-20240702232646501

3.2. 系統時間賦值

這時可以設置開始時間和結束時間。

// 設置時間邊界
const start = Cesium.JulianDate.fromDate(new Date(2015, 1, 1, 11));
const stop = Cesium.JulianDate.addSeconds(start,timeObj.timeSum,new Cesium.JulianDate()
);

光是拿到時間沒有用,需要給系統時間賦值。

// 設置時間段
viewer.clock.startTime = start.clone();
viewer.clock.stopTime = stop.clone();
viewer.clock.currentTime = start.clone(); //當前時間

3.3. 采樣位置

定義了一個名為 getSampleData 的函數,該函數接受三個參數:pArr(軌跡點數組)、start(開始時間)和 siteTime(時間戳數組)。函數的實現原理是將軌跡點數組 pArr 中的每個點按照時間戳數組 siteTime 中的對應時間添加到 position 對象中,從而形成一個采樣位置屬性。也就是將軌跡點數據轉換為 Cesium 可以理解的格式,從而在地圖上繪制軌跡。

為什么要傳入siteTime時間節點傳過來呢?

因為我們算出的時間節點都是從 0 開始算的,但是我們要把時間換算到系統里面去,應該是開始的時間加上時間節點。

這個案例最重點的地方:計算每個軌跡點對應的系統時間

for (let i = 0; i < pArr.length; i++) {//每一個軌跡點所對應的系統時間const time = Cesium.JulianDate.addSeconds(start,siteTime[i],new Cesium.JulianDate());position.addSample(time, pArr[i]);
}
console.log(position);

如果能在_property._values 中拿到 996 個坐標以及 332 個所對應的系統時間,那就是沒問題了,因為笛卡爾是三個坐標。

image-20240702234146455

3.4. 加載公交車

根據實體的速度來計算其朝向。

orientation: new Cesium.VelocityOrientationProperty(position);

將創建的實體設置為視圖的跟蹤實體。跟蹤實體是視圖中的一個實體,當我們在視圖中移動時,它會自動跟隨我們的位置。

viewer.trackedEntity = entity;

如何使公交車在站牌停下?

  1. 需要監聽時鐘
  2. 將當前的公交車坐標和站牌的坐標做比較
  3. 獲取它們之間的距離,在一定范圍內,則停止
// 監聽公交車的運動
viewer.clock.onTick.addEventListener(tickEventHandler);
// 獲取當前的時間公交車的坐標
let startPosition = entity.position.getValue(viewer.clock.currentTime);
// console.log(a);
// 獲取站牌的坐標 比較第二個站點
let endPosition = Cesium.Cartesian3.fromDegrees(...loadData.stations[data.index + 1].xy_coords.split(";").map((a) => Number(a))
);// 得到他們之間的距離
let distance = spaceDistance(startPosition, endPosition);

這里的距離應該是車的中心點到站牌的距離

如果小于一定的距離,就讓公交車停下來,也就是 viewer.clock.shouldAnimate = false;

3.5. 氣泡窗跟隨

獲取當前的坐標,將氣泡窗的位置進行更新。

image-20240703085708150

4. 面板展示

第一欄是起點與目的地,第二欄是編號和站牌名字,第三欄是車輛控制器:暫停,減速,加速,重置,跟隨視角,車內視角,自由視角,速度以及進度條。

image-20240703085025489

4.1. 起點與目的地

獲取站牌的名稱,包括起點和目的地。

data.fromName = loadData.stations[data.index].name;
data.toName = loadData.stations[data.index + 1].name;

4.2. 站牌名字

加載站牌名字到面板上,這里有一些動畫效果,到站時,展示面板也要高亮顯示,并挪動圖標。

if (data.index >= 12 && data.index < 24) {img.value.style.top = "195px";img.value.style.left = 17 + (data.index - 12) * 32.85 + "px";
} else if (data.index >= 24) {img.value.style.top = "385px";img.value.style.left = 17 + (data.index - 24) * 32.85 + "px";
} else {img.value.style.left = 17 + data.index * 32.85 + "px";
}

點擊站牌,也可以實現跳轉到相應的站牌。

// 跳轉到站牌
const toStation = (index) => {changeView("free");if (pickLabel) {pickLabel.label.fillColor = Cesium.Color.WHITE;}pickLabel = viewer.entities.getById("label" + index);// console.log(pickLabel);pickLabel.label.fillColor = Cesium.Color.YELLOW;viewer.flyTo(pickLabel);
};

4.3. 車輛控制器

播放按鈕,設置播放狀態,點擊后播放,變為暫停按鈕,再次點擊,變為播放按鈕。

if (!isBegin) {isBegin = true;toBegin();
}
data.control.play = true;
viewer.clock.shouldAnimate = true;

暫停就是把時間進行暫停。

viewer.clock.shouldAnimate = false;

重播時間就是讓系統的當前時間再等于一下系統的開始時間,圖標,進度條,站牌都還原。

img.value.style.top = "10px";
img.value.style.left = "17px";
data.control.percentage = 0;
data.index = 0;
viewer.clock.currentTime = viewer.clock.startTime;
data.fromName = loadData.stations[0].name;
data.toName = loadData.stations[1].name;

公交車的進度條,根據 s=vt,我們需要計算的是時間,用當前花費的時間除以總時間,可以得到進度條,花費的時間可以用當前時間戳減去開始時間戳。

4.4. 視角切換

自由視角就是取消跟隨視角 viewer.trackedEntity = null;和擺脫觀察者模式 viewer.camera.lookAtTransform(Cesium.Matrix4.IDENTITY);

車內視角就是行駛時更新相機的朝向,使其始終朝向前方。

根據車內的坐標系,可以確定相機放的位置。相機的位置不能寫(0,0,0),不能跟放的東西是同一個點,會報錯的。

viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(-0.001, 0, 0)); //將相機向后面放一點

image-20240703092327068

不管你如何修改上面的三個值,你都無法實現車內的視角,原因是我們所看向的點永遠在車底,我們拿到的實時坐標是沒有高度的,永遠是 0。我們應該要把中心點提一下,x 軸往后一點,這樣就可以實現了。

// 改變視角 公交車內
let cartographic = Cesium.Cartographic.fromCartesian(startPosition);
let lon = Cesium.Math.toDegrees(cartographic.longitude);
let lat = Cesium.Math.toDegrees(cartographic.latitude);
let newPosition = Cesium.Cartesian3.fromDegrees(lon, lat, 2);
if (isInCar) {viewer.trackedEntity = null;var ori = entity.orientation.getValue(viewer.clock.currentTime); //獲取偏向角// var center = entity.position.getValue(viewer.clock.currentTime); //獲取位置var transform = Cesium.Matrix4.fromRotationTranslation(Cesium.Matrix3.fromQuaternion(ori),newPosition); //將偏向角轉為3*3矩陣,利用實時點位轉為4*4矩陣viewer.camera.lookAtTransform(transform, new Cesium.Cartesian3(-0.001, 0, 0)); //將相機向后面放一點
}

image-20240703093022682

車內視角參考:cesium 巡邏獲取對象實時信息并實現切換第一人稱視角

4.5. 后端數據模擬

模擬后端給你一個點,從這個點開始跑,[114.406979, 30.462812]

第一個思路:從所有的軌跡點鐘中選出后端的點,但是后端提供的點不一定在軌跡點上,也有可能有軌跡點的連線上。

第二個思路:算出后端給的點跑了多久,就當時間給回系統時間。可以用該點到起始點的距離除以總的路程,再乘以時間綜合。

使用 turf 庫的線段截取,獲取一條線、起點和終點,并返回這些點之間的線段。起止點不需要正好落在直線上。注意都是 geojson 數據!

let xyArr = [];
let xArr = loadData.xs.split(",");
let yArr = loadData.ys.split(",");
xArr.forEach((item, index) => {positions.push(Cesium.Cartesian3.fromDegrees(Number(item), Number(yArr[index])));xyArr.push([Number(item), Number(yArr[index])]);
});
lineGeoJson = turf.lineString(xyArr);
const start = turf.point(lineGeoJson.geometry.coordinates[0]); //起點
const stop = turf.point([114.406979, 30.462812]); //終點
const sliced = turf.lineSlice(start, stop, lineGeoJson); //線
// console.log(sliced);

計算截取的長度/總長度的百分比,并求出相應的時間

return turf.length(sliced) / turf.length(lineGeoJson);
const proportion = getProportion(); //getProportion是返回截取的長度/總長度的百分比
const newTime = Cesium.JulianDate.addSeconds(start,timeObj.timeSum * proportion,new Cesium.JulianDate()
);

同時還要考慮公交車是否到站了

第一個思路;,后端的點需要跟所有的站點進行比較,拿到最小的距離。但是當線路是 U 型彎回來的時候,如果馬路對面的站點比較近,就和實際效果不一樣。

image-20240703102436588

第二個思路:遍歷所有的站點到起始點的距離,用來跟截取的線段長度做比較,如果截取的線段長度小于站點到起始點線段長度,說明找到了更接近的站點,將當前點的索引(i)賦值給 index。

// 截取站牌長度比較
loadData.stations.forEach((item, i) => {const stationsStop = item.xy_coords.split(";").map((a) => Number(a));const stationsSliced = turf.lineSlice(start, stationsStop, lineGeoJson);// console.log(stationsSliced);if (turf.length(stationsSliced) < turf.length(sliced)) {index = i;}
});

4.6. 調整速度

根據 s=vt,s 不變,如果要更改 v 的話,其他都會發生改變,只有當時間變快時,速度就可以變得快。

4.7. 滾動屏

根據公交車與站牌的距離,顯示滾動屏的內容,距離小于一定的值,就會顯示前方到站 xxx,到了站點起步,就會顯示下一站 xxx,然后過一會時間就會恢復初始的內容。

QQ錄屏20240703104224 -original-original

5. 事件監聽器

當監聽網頁切走后,公交車將會暫停。

// 監聽用戶是否離開頁面 離開 公交車停止運動
document.addEventListener("visibilitychange", function () {if (document.hidden) {viewer.clock.shouldAnimate = false;data.control.play = false;}
});

6. 移除事件

當公交車到達終點后,會清除所有的事件。

const removeEvent = () => {bubble.windowClose();viewer.clock.onTick.removeEventListener(tickEventHandler);viewer.entities.remove(entity);changeView("free");isBegin = false;data.control.play = false;viewer.clock.shouldAnimate = false;
};

也會彈出到達終點。

if (data.index == loadData.stations.length - 1) {alert("We are arrive the terminal.乘客們,感謝您一路對我們工作理解和支持的,下車前請檢查一下自己的行李物品,請不要遺忘在車廂內。");removeEvent();return;
}

參考案例:Cesium 官方車輛軌跡漫游

image-20240702230945514

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/39750.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/39750.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/39750.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【高中數學/基本不等式】已知:x,y均為正實數,且xy+2x+y=4 求:x+y的最小值?

【問題】 已知&#xff1a;x,y均為正實數&#xff0c;且xy2xy4 求&#xff1a;xy的最小值&#xff1f; 【來源】 https://www.ixigua.com/7147585275823292942?logTagf25494de7fce23a3a3d0 【解答】 解&#xff1a; 由xy2xy4 兩邊加二得 xy2xy24 2 分解因式得 (x1)(…

0090__【Git系列】merge和rebase的區別

【Git系列】merge和rebase的區別_rebase和merge的區別-CSDN博客 git中rebase和merge的區別是什么-git-PHP中文網 https://blog.51cto.com/qzcsbj/9444199

從零搭建教育管理系統:Java + Vue.js 教學-02

第三步:創建實體類和 Mapper 接口 現在我們已經設計好了數據庫表,接下來使用 MyBatis-Plus 將這些表映射到 Java 對象,以便在代碼中輕松地進行操作。 1. 創建實體類 在 src/main/java/<your_package>/entity 目錄下 (如果沒有該目錄,請手動創建),創建與數據庫表對應…

MyBatis(20)MyBatis 事務管理如何實現

MyBatis 的事務管理是通過底層 JDBC 連接的事務管理機制來實現的。事務管理對于任何涉及多個數據庫操作的應用程序來說都是至關重要的&#xff0c;它確保數據的一致性和完整性。在 MyBatis 中&#xff0c;事務管理可以通過 SQL 會話&#xff08;SqlSession&#xff09;來實現。…

【WEB前端2024】3D智體編程:喬布斯3D紀念館-第53課-語音指令跳舞

【WEB前端2024】3D智體編程&#xff1a;喬布斯3D紀念館-第53課-語音指令跳舞 使用dtns.network德塔世界&#xff08;開源的智體世界引擎&#xff09;&#xff0c;策劃和設計《喬布斯超大型的開源3D紀念館》的系列教程。dtns.network是一款主要由JavaScript編寫的智體世界引擎&…

可信計算的完整專用名詞列表

可信計算的完整專用名詞列表 Trusted Computing - 可信計算Trusted Platform Module (TPM) - 可信平臺模塊Hardware Root of Trust - 硬件根信任Secure Boot - 安全啟動Remote Attestation - 遠程證明Integrity Measurement - 完整性度量Measurement Log - 度量日志Attestatio…

Android 圖像效果的奧秘

在當今數字化時代&#xff0c;圖像已經成為人們生活和工作中不可或缺的一部分。而在 Android 系統中&#xff0c;圖像效果的應用更是豐富多彩&#xff0c;為用戶帶來了更加出色的視覺體驗。本文將深入探討 Android 圖像效果的原理、實現方法以及應用場景&#xff0c;幫助讀者更…

面試題springboot面試

文章目錄 Spring的依賴注入構造器注入stetter注入屬性注入 springboot的優勢第一開箱即用約定大于配置內嵌tomcat服務器 javaweb的三大組件springboot的自動配置原理SpringIoc的實現機制springmvcspring如何簡化開發 Spring的依賴注入 構造器注入 stetter注入 屬性注入 使用…

按位異或^

在 Python 中&#xff0c;a ^ b 表示按位異或運算符。按位異或運算符對整數的每一位進行運算&#xff0c;如果對應位上的兩個二進制數字不同&#xff0c;則結果為 1&#xff0c;否則為 0。 示例 a 5 # 二進制: 0101 b 3 # 二進制: 0011result a ^ b print(result) # 輸…

私域流量:塑造企業數字營銷的未來

在當今數字化的時代&#xff0c;流量成為了商業世界中的新貨幣&#xff0c;而“私域流量”更是其中的黃金。但“私域流量”究竟是什么&#xff1f;它如何成為企業數字化轉型和營銷策略中不可或缺的一部分&#xff1f;本文將探討私域流量的概念&#xff0c;并通過案例分析其運營…

前端進階:Vue.js

目錄 框架&#xff1a; 助解&#xff1a; 框架&#xff1a; VUE 什么是Vue.js? Vue.js優點 Vue安裝 方式一&#xff1a;直接用<script>引入 方式二&#xff1a;命令行工具 第一個Vue程序 代碼 代碼解釋&#xff1a; 運行 Vue指令 v-text v-html v-tex…

Mysql和ES使用匯總

一、mysql和ES在業務上的配合使用 一般使用時使用ES 中存儲全文檢索的關鍵字與獲取的商品詳情的id&#xff0c;通過ES查詢獲取查詢商品的列表中展示的數據&#xff0c;通過展示id 操作去獲取展示商品的所有信息。mysql根據id去查詢數據庫數據是很快的&#xff1b; 為什么ES一般…

JavaScript如何聲明json對象

在JavaScript中&#xff0c;JSON&#xff08;JavaScript Object Notation&#xff09;對象實際上是以JavaScript對象的形式表示的。JSON是一種輕量級的數據交換格式&#xff0c;它基于ECMAScript&#xff08;歐洲計算機協會制定的js規范&#xff09;的一個子集&#xff0c;采用…

10 - Python文件編程和異常

文件和異常 在實際開發中&#xff0c;常常需要對程序中的數據進行持久化操作&#xff0c;而實現數據持久化最直接簡單的方式就是將數據保存到文件中。說到“文件”這個詞&#xff0c;可能需要先科普一下關于文件系統的知識&#xff0c;對于這個概念&#xff0c;維基百科上給出…

【CSharp】在class中申明public const int常量的應用

【CSharp】在class中申明public const int常量的應用 1.背景2.代碼3.運行1.背景 常量本身是靜態的,即常量屬于class本身與其實例化對象無關,且常量不可更改。 以上兩種特性在許多應用場景中都有其優勢和應用場合。 1.在定義定義固定值的場景,例如狀態碼、事件類型、配置參…

亞馬遜云科技AWS免費大熱AI應用開發證書(含題庫、開卷)

亞馬遜云科技AWS官方生成式AI免費證書來了&#xff01;內含免費AI基礎課程&#xff01;快速掌握AWS的前沿AI技術&#xff0c;后端開發程序員也可以速成AI專家&#xff0c;了解當下最&#x1f525;的AWS AI架構解決方案&#xff01; 本證書內容包括AWS上的AI基礎知識&#xff0c…

解析Kotlin中的Unit【筆記摘要】

1. Kotlin的Unit 和 Java的void 的區別 // Java public void sayHello() {System.out.println("Hello!") }// Kotlin fun sayHello(): Unit {println("Hello!") }Unit 和 Java 的 void 真正的區別在于&#xff0c;void 是真的表示什么都不返回&#xff0c…

剖析DeFi交易產品之UniswapV4:Swap

文章首發于公眾號&#xff1a;Keegan小鋼 Swap 可分為兩種場景&#xff1a;單池交易和跨池交易。在 PoolManager 合約里&#xff0c;要完成交易流程&#xff0c;會涉及到 lock()、swap()、settle()、take() 四個函數。單池交易時只需要調一次 swap() 函數&#xff0c;而跨池交易…

【面向就業的Linux基礎】從入門到熟練,探索Linux的秘密(七)-shell語法(5)

shell語法的一些知識和練習&#xff0c;可以當作筆記收藏一下&#xff01;&#xff01; 文章目錄 前言 一、shell 二、shell語法 1.文件重定向 2.引入外部腳本 3.作業 總結 前言 shell語法的一些知識和練習&#xff0c;可以當作筆記收藏一下&#xff01;&#xff01; 提示&…

七種大模型微調方法:讓你的Offer拿到爽

在當今的人工智能和機器學習領域&#xff0c;大型預訓練模型&#xff08;如GPT、BERT等&#xff09;已成為解決自然語言處理&#xff08;NLP&#xff09;任務的強大工具。然而&#xff0c;要讓這些模型更好地適應特定任務或領域&#xff0c;往往需要進行微調。本文將詳細介紹七…