curve_integral_conversion.py
1from manim import *2import numpy as np3 4config.tex_template = TexTemplateLibrary.ctex5config.tex_template.add_to_preamble(r"\setCJKmainfont{STSong}")6 7 8class CurveIntegralConversion(Scene):9 def construct(self):10 # ========== 标题 ==========11 title = Text('两类曲线积分的转换', font="SimSun", color=YELLOW).scale(0.65)12 title.to_edge(UP, buff=0.3)13 self.play(Write(title), run_time=1)14 self.wait(0.3)15 16 # =============================================17 # 场景1:问题引入——为什么要转换?18 # =============================================19 # 曲线(左到右,波浪形,保证切线角α为正锐角)20 curve_func = lambda t: np.array([21 -2.0 + 1.5 * t,22 0.8 * np.sin(1.8 * t) - 0.3,23 024 ])25 curve = ParametricFunction(curve_func, t_range=[0.2, 2.5], color=WHITE, stroke_width=3)26 self.play(Create(curve), run_time=1.5)27 28 # 起终点29 start_dot = Dot(curve_func(0.2), color=GREEN, radius=0.07)30 end_dot = Dot(curve_func(2.5), color=RED, radius=0.07)31 A_label = MathTex("A", color=GREEN).scale(0.35).next_to(start_dot, DL, buff=0.05)32 B_label = MathTex("B", color=RED).scale(0.35).next_to(end_dot, DR, buff=0.05)33 self.play(FadeIn(start_dot), FadeIn(end_dot), Write(A_label), Write(B_label), run_time=0.6)34 35 # 向量场 F=(P,Q)36 def F_field(pos):37 x, y = pos[0], pos[1]38 return np.array([0.4 * y + 0.3, -0.3 * x + 0.4, 0])39 40 field_arrows = VGroup()41 for t_val in np.linspace(0.3, 2.4, 10):42 pos = curve_func(t_val)43 F_val = F_field(pos)44 F_norm = np.linalg.norm(F_val)45 if F_norm > 0.01:46 F_dir = F_val / F_norm * 0.547 arr = Arrow(pos, pos + F_dir, buff=0, color=BLUE_C, stroke_width=2.5, tip_length=0.08)48 field_arrows.add(arr)49 self.play(LaggedStartMap(Create, field_arrows, lag_ratio=0.06), run_time=1.2)50 51 f_label = MathTex(r"\vec{F}=(P,Q)", color=BLUE_C).scale(0.38)52 f_label.next_to(curve, UP, buff=0.3).shift(RIGHT * 0.5)53 self.play(Write(f_label), run_time=0.5)54 55 # 问题:计算第二型积分56 problem_eq = MathTex(r"\text{求:}\ \int_L P\,dx + Q\,dy\ = \ ?", color=BLUE).scale(0.45)57 problem_eq.to_edge(LEFT, buff=0.4).shift(UP * 2.5)58 self.play(Write(problem_eq), run_time=1)59 self.wait(0.8)60 61 # 动机文字62 motive = Text('能否转化为对弧长的积分?', font="SimSun", color=WHITE).scale(0.3)63 motive.next_to(problem_eq, RIGHT, buff=0.3)64 self.play(Write(motive), run_time=0.8)65 self.wait(1.5)66 67 # 清理场景1(保留曲线、起终点)68 self.play(69 FadeOut(field_arrows), FadeOut(f_label),70 FadeOut(problem_eq), FadeOut(motive),71 run_time=0.6,72 )73 74 # =============================================75 # 场景2:关键洞察——切向量76 # =============================================77 scene2_label = Text('关键:切向量 T', font="SimSun", color=ORANGE).scale(0.3)78 scene2_label.to_edge(LEFT, buff=0.4).shift(UP * 2.5)79 self.play(Write(scene2_label), run_time=0.5)80 81 # 动态切向量82 def get_tangent_at(t_val):83 dt = 0.0184 p1 = curve_func(t_val)85 p2 = curve_func(t_val + dt)86 T = (p2 - p1) / np.linalg.norm(p2 - p1)87 return T88 89 t_tracker = ValueTracker(0.5)90 moving_point = always_redraw(91 lambda: Dot(curve_func(t_tracker.get_value()), color=ORANGE, radius=0.08)92 )93 tangent_arrow = always_redraw(94 lambda: Arrow(95 curve_func(t_tracker.get_value()),96 curve_func(t_tracker.get_value()) + get_tangent_at(t_tracker.get_value()) * 1.0,97 buff=0, color=ORANGE, stroke_width=3.5, tip_length=0.12,98 )99 )100 t_label_dyn = always_redraw(101 lambda: MathTex(r"\vec{T}", color=ORANGE).scale(0.38).next_to(102 curve_func(t_tracker.get_value()) + get_tangent_at(t_tracker.get_value()) * 1.0,103 UR, buff=0.03,104 )105 )106 107 self.play(FadeIn(moving_point), Create(tangent_arrow), Write(t_label_dyn), run_time=0.6)108 self.play(t_tracker.animate.set_value(0.5), run_time=2.0, rate_func=linear)109 self.wait(0.3)110 111 # 冻结在 t=0.5(α≈30°,正锐角,位置清晰)112 t_stop = t_tracker.get_value()113 P_pos = curve_func(t_stop)114 T_vec = get_tangent_at(t_stop)115 self.remove(moving_point, tangent_arrow, t_label_dyn)116 117 static_point = Dot(P_pos, color=ORANGE, radius=0.08)118 static_tangent = Arrow(119 P_pos, P_pos + T_vec * 1.0,120 buff=0, color=ORANGE, stroke_width=3.5, tip_length=0.12,121 )122 static_t_label = MathTex(r"\vec{T}", color=ORANGE).scale(0.38)123 static_t_label.next_to(static_tangent.get_end(), UR, buff=0.03)124 self.add(static_point, static_tangent, static_t_label)125 126 # x轴参考线 + 角度127 x_ref = DashedLine(P_pos + LEFT * 0.2, P_pos + RIGHT * 1.3, color=GREY, stroke_width=1.5)128 self.play(Create(x_ref), run_time=0.4)129 130 alpha_val = np.arctan2(T_vec[1], T_vec[0])131 angle_arc = Angle(132 Line(P_pos, P_pos + RIGHT), Line(P_pos, P_pos + T_vec),133 radius=0.3, color=RED_C,134 )135 alpha_label = MathTex(r"\alpha", color=RED_C).scale(0.35)136 alpha_label.move_to(P_pos + 0.45 * np.array([np.cos(alpha_val / 2), np.sin(alpha_val / 2), 0]))137 self.play(Create(angle_arc), Write(alpha_label), run_time=0.8)138 139 # 分解为直角三角形140 dx_comp = np.array([T_vec[0], 0, 0]) * 1.0141 dy_comp = np.array([0, T_vec[1], 0]) * 1.0142 143 h_line = DashedLine(P_pos, P_pos + dx_comp, color=RED_C, stroke_width=2.5)144 v_line = DashedLine(P_pos + dx_comp, P_pos + dx_comp + dy_comp, color=TEAL, stroke_width=2.5)145 self.play(Create(h_line), Create(v_line), run_time=0.8)146 147 # 标注分量148 cos_a_label = MathTex(r"\cos\alpha", color=RED_C).scale(0.3)149 cos_a_label.next_to(h_line, DOWN, buff=0.05)150 cos_b_label = MathTex(r"\cos\beta", color=TEAL).scale(0.3)151 cos_b_label.next_to(v_line, RIGHT, buff=0.05)152 self.play(Write(cos_a_label), Write(cos_b_label), run_time=0.6)153 154 # 右侧公式155 formula_T = MathTex(r"\vec{T} = (\cos\alpha,\ \cos\beta)", color=ORANGE).scale(0.4)156 formula_T.to_edge(RIGHT, buff=0.4).shift(UP * 1.8)157 self.play(Write(formula_T), run_time=0.8)158 self.wait(1.5)159 160 self.play(FadeOut(scene2_label), run_time=0.3)161 162 # =============================================163 # 场景3:微元关系 ds, dx, dy164 # =============================================165 scene3_label = Text('微元关系:ds → dx, dy', font="SimSun", color=WHITE).scale(0.28)166 scene3_label.to_edge(LEFT, buff=0.4).shift(UP * 2.5)167 self.play(Write(scene3_label), run_time=0.5)168 169 # 用高亮曲线段表示 ds(实际弧长)170 dt_small = 0.35171 arc_segment = ParametricFunction(172 curve_func, t_range=[t_stop, t_stop + dt_small],173 color=YELLOW, stroke_width=5,174 )175 arc_end = curve_func(t_stop + dt_small)176 ds_brace = BraceBetweenPoints(P_pos, arc_end, color=YELLOW)177 ds_label = MathTex("ds", color=YELLOW).scale(0.4)178 ds_label.next_to(ds_brace, ds_brace.get_direction(), buff=0.05)179 self.play(Create(arc_segment), run_time=0.6)180 self.play(Create(ds_brace), Write(ds_label), run_time=0.6)181 182 # 显示切线段≈弧长段183 tangent_end = P_pos + T_vec * np.linalg.norm(arc_end - P_pos)184 tangent_seg = Line(P_pos, tangent_end, color=ORANGE, stroke_width=4)185 approx_text = MathTex(r"\text{\color{yellow}弧长} \approx \text{\color{orange}切线段}", color=WHITE).scale(0.3)186 approx_text.next_to(ds_brace, ds_brace.get_direction(), buff=0.35)187 self.play(Create(tangent_seg), Write(approx_text), run_time=0.8)188 self.wait(1)189 190 # 分解切线段为 dx, dy191 seg_len = np.linalg.norm(arc_end - P_pos)192 dx_comp_seg = np.array([T_vec[0], 0, 0]) * seg_len193 dy_comp_seg = np.array([0, T_vec[1], 0]) * seg_len194 h_line_seg = DashedLine(P_pos, P_pos + dx_comp_seg, color=RED_C, stroke_width=2.5)195 v_line_seg = DashedLine(P_pos + dx_comp_seg, P_pos + dx_comp_seg + dy_comp_seg, color=TEAL, stroke_width=2.5)196 self.play(Create(h_line_seg), Create(v_line_seg), run_time=0.6)197 198 # 标注 dx, dy199 dx_label = MathTex("dx", color=RED_C).scale(0.3)200 dx_label.next_to(h_line_seg, DOWN, buff=0.12)201 dy_label = MathTex("dy", color=TEAL).scale(0.3)202 dy_label.next_to(v_line_seg, RIGHT, buff=0.1)203 self.play(Write(dx_label), Write(dy_label), run_time=0.5)204 205 # 局部放大:复制几何元素居中放大显示206 zoom_copy = VGroup(207 arc_segment.copy(),208 tangent_seg.copy(),209 ds_brace.copy(), ds_label.copy(),210 h_line_seg.copy(), v_line_seg.copy(),211 dx_label.copy(), dy_label.copy(),212 angle_arc.copy(), alpha_label.copy(),213 static_point.copy(),214 )215 zoom_copy.scale(2.5).move_to(ORIGIN + LEFT * 0.5)216 zoom_bg = SurroundingRectangle(zoom_copy, color=WHITE, buff=0.2, corner_radius=0.1, fill_color=BLACK, fill_opacity=0.85)217 zoom_title = Text('放大:曲线段 ds → dx, dy', font="SimSun", color=YELLOW).scale(0.3)218 zoom_title.next_to(zoom_bg, UP, buff=0.1)219 self.play(FadeIn(zoom_bg), FadeIn(zoom_copy), Write(zoom_title), run_time=1)220 self.wait(3)221 self.play(FadeOut(zoom_bg), FadeOut(zoom_copy), FadeOut(zoom_title), run_time=0.8)222 223 # 关键公式(带闪烁提示)224 key_eq1 = MathTex(r"dx = \cos\alpha \cdot ds", color=RED_C).scale(0.42)225 key_eq1.next_to(formula_T, DOWN, buff=0.25)226 key_eq2 = MathTex(r"dy = \cos\beta \cdot ds", color=TEAL).scale(0.42)227 key_eq2.next_to(key_eq1, DOWN, buff=0.1)228 229 # 闪烁 h_line 同时写公式230 self.play(Write(key_eq1), h_line.animate.set_color(YELLOW), run_time=1)231 self.play(h_line.animate.set_color(RED_C), run_time=0.3)232 self.play(Write(key_eq2), v_line.animate.set_color(YELLOW), run_time=1)233 self.play(v_line.animate.set_color(TEAL), run_time=0.3)234 235 bridge_text = Text('这就是连接两类积分的桥梁!', font="SimSun", color=YELLOW).scale(0.25)236 bridge_text.next_to(key_eq2, DOWN, buff=0.15)237 self.play(Write(bridge_text), run_time=0.8)238 self.wait(2)239 240 # =============================================241 # 场景4:代入——得到转换公式242 # =============================================243 # 清理几何元素(保留曲线)244 geom_objs = VGroup(245 static_point, static_tangent, static_t_label,246 x_ref, angle_arc, alpha_label,247 h_line, v_line, cos_a_label, cos_b_label,248 arc_segment, tangent_seg, approx_text,249 h_line_seg, v_line_seg,250 ds_brace, ds_label, dx_label, dy_label,251 scene3_label, bridge_text,252 )253 self.play(FadeOut(geom_objs), run_time=0.8)254 255 # 推导放在右侧(下移避免重叠),曲线在左侧保留256 sub_title = Text('代入 dx, dy:', font="SimSun", color=WHITE).scale(0.28)257 sub_title.to_edge(RIGHT, buff=1.2).shift(DOWN * 0.2)258 self.play(Write(sub_title), run_time=0.5)259 260 line1 = MathTex(r"\int_L", r"P\,dx", r"+", r"Q\,dy", color=BLUE).scale(0.38)261 line1.next_to(sub_title, DOWN, buff=0.1)262 self.play(Write(line1), run_time=0.8)263 264 # 高亮 dx, dy265 self.play(266 line1[1].animate.set_color(RED_C),267 line1[3].animate.set_color(TEAL),268 run_time=0.5,269 )270 271 line2 = MathTex(272 r"= \int_L P\cos\alpha\,ds + Q\cos\beta\,ds",273 color=WHITE,274 ).scale(0.34)275 line2.next_to(line1, DOWN, buff=0.08)276 self.play(Write(line2), run_time=1.2)277 278 # 最终公式(黄色高亮框,包含完整等式,左移避免出框)279 final_eq = MathTex(280 r"\int_L P\,dx + Q\,dy",281 r"=",282 r"\int_L (P\cos\alpha + Q\cos\beta)\,ds",283 color=WHITE,284 ).scale(0.36)285 final_eq[0].set_color(BLUE)286 final_eq[2].set_color(YELLOW)287 final_eq.next_to(line2, DOWN, buff=0.12).shift(LEFT * 0.3)288 final_box = SurroundingRectangle(final_eq, color=YELLOW, buff=0.08, corner_radius=0.05)289 self.play(Write(final_eq), Create(final_box), run_time=1.5)290 self.wait(2)291 292 # 清理推导细节,保留最终公式293 deriv_cleanup = VGroup(formula_T, key_eq1, key_eq2, sub_title, line1, line2)294 self.play(FadeOut(deriv_cleanup), run_time=0.6)295 296 # 将最终公式移到上方保留297 self.play(298 final_eq.animate.scale(0.9).next_to(title, DOWN, buff=0.2),299 final_box.animate.scale(0.9).next_to(title, DOWN, buff=0.2),300 run_time=1,301 )302 new_box = SurroundingRectangle(final_eq, color=YELLOW, buff=0.08, corner_radius=0.05)303 self.play(Transform(final_box, new_box), run_time=0.3)304 305 # =============================================306 # 场景5:几何意义——向量场在切线方向的投影307 # =============================================308 # 重新显示向量场309 field_arrows2 = VGroup()310 for t_val in np.linspace(0.3, 2.4, 10):311 pos = curve_func(t_val)312 F_val = F_field(pos)313 F_norm = np.linalg.norm(F_val)314 if F_norm > 0.01:315 F_dir = F_val / F_norm * 0.5316 arr = Arrow(pos, pos + F_dir, buff=0, color=BLUE_C, stroke_width=2, tip_length=0.07)317 field_arrows2.add(arr)318 self.play(LaggedStartMap(Create, field_arrows2, lag_ratio=0.05), run_time=1.2)319 320 # 明确说明:被积函数 Pcosα+Qcosβ 的几何意义321 geo_title = MathTex(322 r"P\cos\alpha + Q\cos\beta",323 r"\ = \ ",324 r"\vec{F}\cdot\vec{T}",325 r"\ = \ ",326 r"\text{向量场在切线上的投影}",327 color=WHITE,328 ).scale(0.32)329 geo_title[0].set_color(YELLOW)330 geo_title[2].set_color(ORANGE)331 geo_title[4].set_color(YELLOW)332 geo_title.to_edge(DOWN, buff=0.5)333 self.play(Write(geo_title), run_time=1)334 335 # 动态投影演示336 proj_tracker = ValueTracker(0.5)337 338 demo_dot = always_redraw(339 lambda: Dot(curve_func(proj_tracker.get_value()), color=WHITE, radius=0.07)340 )341 342 def make_proj_visual():343 t_val = proj_tracker.get_value()344 pos = curve_func(t_val)345 T = get_tangent_at(t_val)346 F_val = F_field(pos)347 F_norm = np.linalg.norm(F_val)348 if F_norm < 0.01:349 return VGroup()350 F_dir = F_val / F_norm * 0.65351 f_arr = Arrow(pos, pos + F_dir, buff=0, color=BLUE, stroke_width=3, tip_length=0.1)352 t_arr = Arrow(pos, pos + T * 0.65, buff=0, color=ORANGE, stroke_width=3, tip_length=0.1)353 proj_len = np.dot(F_dir, T)354 proj_end = pos + T * proj_len355 proj_arr = Arrow(pos, proj_end, buff=0, color=YELLOW, stroke_width=3.5, tip_length=0.09)356 drop = DashedLine(pos + F_dir, proj_end, color=GREY_B, stroke_width=1.5)357 return VGroup(f_arr, t_arr, proj_arr, drop)358 359 proj_visual = always_redraw(make_proj_visual)360 self.add(demo_dot, proj_visual)361 self.wait(0.3)362 363 self.play(proj_tracker.animate.set_value(2.5), run_time=5, rate_func=linear)364 self.wait(1)365 366 # 清理367 self.remove(demo_dot, proj_visual)368 self.play(FadeOut(field_arrows2), FadeOut(geo_title), run_time=0.6)369 370 # =============================================371 # 场景6:方向性备注(配合切向量动画演示)372 # =============================================373 # 左侧:重新显示曲线 + 切向量动画演示方向反转374 dir_title = Text('补充:方向性', font="SimSun", color=ORANGE).scale(0.35)375 dir_title.to_edge(LEFT, buff=0.4).shift(UP * 2.5)376 self.play(Write(dir_title), run_time=0.5)377 378 # 正向切向量(锐角α)379 t_demo = 0.5380 P_demo = curve_func(t_demo)381 T_fwd = get_tangent_at(t_demo)382 fwd_arrow = Arrow(P_demo, P_demo + T_fwd * 1.2, buff=0, color=GREEN, stroke_width=4, tip_length=0.12)383 fwd_label = MathTex(r"\vec{T}", color=GREEN).scale(0.4).next_to(fwd_arrow.get_end(), UR, buff=0.05)384 385 # x轴参考线 + 角度386 x_ref_dir = DashedLine(P_demo + LEFT * 0.3, P_demo + RIGHT * 1.5, color=GREY, stroke_width=1.5)387 alpha_fwd = np.arctan2(T_fwd[1], T_fwd[0])388 arc_fwd = Angle(389 Line(P_demo, P_demo + RIGHT), Line(P_demo, P_demo + T_fwd),390 radius=0.35, color=GREEN,391 )392 alpha_fwd_label = MathTex(r"\alpha", color=GREEN).scale(0.35)393 alpha_fwd_label.move_to(P_demo + 0.55 * np.array([np.cos(alpha_fwd / 2), np.sin(alpha_fwd / 2), 0]))394 395 dot_demo = Dot(P_demo, color=WHITE, radius=0.07)396 self.play(FadeIn(dot_demo), Create(x_ref_dir), Create(fwd_arrow), Write(fwd_label), run_time=0.8)397 self.play(Create(arc_fwd), Write(alpha_fwd_label), run_time=0.6)398 399 # 右侧:逻辑链说明(正向)400 step0 = Text('正向行走:', font="SimSun", color=GREEN).scale(0.25)401 step0.to_edge(RIGHT, buff=1.2).shift(UP * 1.2)402 step1 = MathTex(403 r"\vec{T} \text{ 指向前方}",404 color=GREEN,405 ).scale(0.33)406 step1.next_to(step0, DOWN, buff=0.08)407 step1_alpha = MathTex(408 r"\Rightarrow \alpha \text{ 为锐角}",409 color=GREEN,410 ).scale(0.33)411 step1_alpha.next_to(step1, DOWN, buff=0.06)412 step1_cos = MathTex(413 r"\Rightarrow \cos\alpha > 0",414 color=GREEN,415 ).scale(0.33)416 step1_cos.next_to(step1_alpha, DOWN, buff=0.06)417 self.play(Write(step0), run_time=0.4)418 self.play(Write(step1), run_time=0.6)419 self.play(Write(step1_alpha), run_time=0.6)420 self.play(Write(step1_cos), run_time=0.6)421 self.wait(1.5)422 423 # 反向切向量(钝角)424 T_bwd = -T_fwd425 bwd_arrow = Arrow(P_demo, P_demo + T_bwd * 1.2, buff=0, color=RED_C, stroke_width=4, tip_length=0.12)426 bwd_label = MathTex(r"-\vec{T}", color=RED_C).scale(0.4).next_to(bwd_arrow.get_end(), DL, buff=0.05)427 428 alpha_bwd = np.arctan2(T_bwd[1], T_bwd[0])429 arc_bwd = Angle(430 Line(P_demo, P_demo + RIGHT), Line(P_demo, P_demo + T_bwd),431 radius=0.35, color=RED_C,432 )433 alpha_bwd_label = MathTex(r"\pi-\alpha", color=RED_C).scale(0.32)434 alpha_bwd_label.move_to(P_demo + 0.6 * np.array([np.cos((np.pi + alpha_bwd) / 2), np.sin((np.pi + alpha_bwd) / 2), 0]))435 436 self.play(437 Transform(fwd_arrow, bwd_arrow),438 Transform(fwd_label, bwd_label),439 Transform(arc_fwd, arc_bwd),440 Transform(alpha_fwd_label, alpha_bwd_label),441 run_time=1.5,442 )443 444 # 右侧:逻辑链说明(反向)445 step2 = Text('反向行走:', font="SimSun", color=RED_C).scale(0.25)446 step2.next_to(step1_cos, DOWN, buff=0.2)447 chain1 = MathTex(448 r"\text{方向反转}",449 r"\Rightarrow",450 r"\vec{T} \to -\vec{T}",451 color=RED_C,452 ).scale(0.33)453 chain1.next_to(step2, DOWN, buff=0.08)454 chain2 = MathTex(455 r"\Rightarrow \alpha \to \pi-\alpha \text{(变为钝角)}",456 color=RED_C,457 ).scale(0.33)458 chain2.next_to(chain1, DOWN, buff=0.06)459 chain3 = MathTex(460 r"\Rightarrow \cos\alpha < 0",461 color=RED_C,462 ).scale(0.33)463 chain3.next_to(chain2, DOWN, buff=0.06)464 self.play(Write(step2), run_time=0.4)465 self.play(Write(chain1), run_time=0.7)466 self.play(Write(chain2), run_time=0.7)467 self.play(Write(chain3), run_time=0.6)468 self.wait(1.5)469 470 # 结论471 dir_c1_note = MathTex(472 r"\therefore\quad",473 r"\int_L (P\cos\alpha+Q\cos\beta)\,ds",474 r"\text{ 变号}",475 color=BLUE,476 ).scale(0.34)477 dir_c1_note.next_to(chain3, DOWN, buff=0.15)478 self.play(Write(dir_c1_note), run_time=0.8)479 self.wait(3)480 481 482def main():483 import os484 os.system("manim -pql curve_integral_conversion.py CurveIntegralConversion")485 486 487if __name__ == "__main__":488 main() 讲解
这个视频围绕公式
展开。动画先提出第二类曲线积分的问题,再把曲线上的局部运动拆成切向量、方向余弦和弧长微元三件事。
开场画面建立曲线、端点和向量场,让观众先看到积分对象。切向量说明部分引入单位切向量 ,并用角度 、 表示它在坐标方向上的分量。
局部近似步骤是转换的核心:把一小段曲线近似为切线段,得到 和 。这一步把第二类积分中的 、 接到第一类积分使用的弧长微元 上。
公式代入步骤完成转换。随后的几何解释把 识别为向量场在切线方向上的投影,也就是 。
结尾的方向性讨论说明:曲线路径反向时,切向量变成 ,方向余弦随之变号,所以第二类曲线积分也会变号。