สร้างภาคไฟใน QGIS?


24

ฉันใช้ QGIS 2.18 ฉันจำเป็นต้องสร้างไฟเซกเตอร์สำหรับวัตถุประสงค์ในการนำทางบนแผนที่

ฉันมีข้อมูลภาคแสงเป็นฟิลด์ที่ให้ becon_id, ปริญญาเริ่มต้น, องศาสิ้นสุดและสีใน shapefile ที่มีมากกว่า 500 ทุ่น, บีคอนและกระโจมไฟที่จำเป็นต้องแสดงบนแผนที่ สำหรับสัญญาณแต่ละอันสามารถมีได้หลายแถวแต่ละแถวอธิบายหนึ่งเซกเมนต์แสง (เช่นเซกเตอร์สีขาว)

ผลลัพธ์สุดท้ายควรมีลักษณะดังนี้: ส่วนแสงในสีที่ถูกต้องโดยสีที่ทำเครื่องหมายเป็นอักขระในฟิลด์สี (RGW) และเส้นประจาก 100m ถึง 1000m จากทุ่น / ประภาคาร / ประภาคาร

สิ่งนี้น่าจะถูกสร้างเป็นสัญลักษณ์ตามหลักปกครอง แต่ต้องการงูใหญ่บางตัวที่ฉันเดา?

ป้อนคำอธิบายรูปภาพที่นี่

ด้านล่างนี้เป็นตัวอย่างของข้อมูลรูปร่างไฟล์สำหรับประภาคาร (น่าเสียดายที่ไม่ใช่ข้อมูลด้านบน) ซึ่งมีเซกเตอร์สีเขียวระหว่าง 114 ถึง 154 องศาเซกเตอร์สีขาวระหว่าง 154 ถึง 168 องศาเซกเตอร์สีแดงระหว่าง 168 และ 237 องศาสีเขียว เซกเตอร์ระหว่าง 237 และ 314 องศาเซกเตอร์สีขาวระหว่าง 314 และ 320 องศาเซกเตอร์สีแดงระหว่าง 320 และ 337 องศา (ด้วยเหตุผลบางอย่าง 0 ไม่ใช่ภาคเหนือ แต่ใต้):

ตัวอย่างตาราง shapefile



2
โปรดคุณสามารถอัปโหลดชุดข้อมูลตัวอย่างและแก้ไขคำถามของคุณโดยอธิบายรายละเอียดผลลัพธ์ที่คุณคาดหวังได้อย่างแน่นอน ในภาพที่แนบมาฉันเห็นเพียงสัญลักษณ์และสีในจักรวาล
mgri

1
ข้อมูลตัวอย่างจะช่วยได้ที่นี่ คุณมีคุณสมบัติหนึ่งอย่างต่อภาคแสงหรือหนึ่งคุณลักษณะต่อทุ่น? ปลั๊กอิน Wedge Buffer อาจช่วยได้ที่นี่ แต่วิธีการที่ง่ายขึ้นอยู่กับการตั้งค่าข้อมูลของคุณ
Steven Kay

สวัสดี @ mgri และ Steven ฉันได้เพิ่มข้อมูลตัวอย่างและพยายามทำให้คำถามชัดเจนขึ้น :) ขอบคุณ!
Benjamin Donner

1
@ mgri the lines ไม่ใช่ตัวแปร แต่บรรทัดที่ควรแสดงแบบสแตติกเป็นเส้นยาว 900m ระหว่างเซกเมนต์แสงเช่นในภาพ ระบบอ้างอิงที่คาดการณ์
Benjamin Donner

คำตอบ:


50

แก้ไขฉันแก้ไขคำตอบสำหรับการจัดการสถานการณ์เฉพาะ (เนื่องจากค่ามุมที่เฉพาะเจาะจง) และไม่แสดงเส้นประเมื่อมีการกำหนดมุมมน


ฉันเสนอวิธีแก้ปัญหาโดยการทำซ้ำตามสัญลักษณ์และการติดฉลากตามกฎเท่านั้น

ก่อนที่จะเริ่มฉันต้องการขีดเส้นใต้ที่ฉันจะมุ่งเน้นความสนใจไปที่คำอธิบายของสิ่งเล็ก ๆ น้อย ๆ ที่จะทำเพื่อให้ได้ผลลัพธ์ที่ต้องการ: นั่นหมายความว่าคุณควรปรับพารามิเตอร์ย่อยอื่น ๆ (เช่นขนาดความกว้างเป็นต้น) เพื่อให้เหมาะกับความต้องการของคุณ

นอกจากนี้วิธีนี้จะใช้งานได้ก็ต่อเมื่อคุณคิดว่า0ระดับนั้นเป็นทิศเหนือแทนที่จะเป็นทิศใต้ (ถ้า0เป็นทิศใต้แทนก็จะเป็นการรวม180ค่าทุกครั้งที่ปรากฏ '90' ในสูตรที่จัดการกับมุมเช่นcos(radians(90))จะกลายเป็นcos(radians(180 + 90))เพียงพอ) ฉันชอบทำสิ่งนี้เพียงเพื่อประโยชน์ในการแก้ปัญหาทั่วไปมากขึ้น


การออกแบบ

เราจะแสดงจุดด้วยSingle symbolและโดยซ้ำกับเลเยอร์สัญลักษณ์หนึ่งSimple MarkerและสามGeometry generator:

ป้อนคำอธิบายรูปภาพที่นี่

ในคำอธิบายเพิ่มเติมฉันจะทำตามลำดับเดียวกันของสัญลักษณ์ในภาพด้านบน

1) เครื่องหมายง่าย

ฉันเลือกสัญลักษณ์เริ่มต้นของดาวสีดำ (นี่เป็นส่วนที่ง่ายกว่าของบทช่วยสอนนี้) มีขนาด 3 มม. และกว้าง 0.4 มม.

2) เครื่องกำเนิดเรขาคณิตที่ 1

เพิ่มเลเยอร์สัญลักษณ์ใหม่และเลือกGeometry generatorประเภท:

ป้อนคำอธิบายรูปภาพที่นี่

แทรกนิพจน์นี้ในExpressionฟิลด์:

CASE
WHEN abs( "ALKUKULMA" - "LOPPUKULMA") < 360
THEN
make_line(
 $geometry,
 make_point(
  $x + 1000*cos(radians(90 - "ALKUKULMA")),
  $y + 1000*sin(radians(90 - "ALKUKULMA"))
  )
)
END

เราเพิ่งกำหนดบรรทัดแรกซึ่งชี้ไปยังจุดที่ภาคแสงเริ่มต้น บรรทัดนี้มีความยาว 1,000 ม. และสร้างขึ้นเฉพาะเมื่อมุมเปิดของแสงเซกเตอร์ไม่ใช่มุมกลม (เกิดขึ้นเพื่อหลีกเลี่ยงว่าเส้นจะแตกเป็นวงกลมทั้งหมด)

3) ตัวสร้างรูปทรงเรขาคณิตหมายเลข 2

เหมือนกับด้านบน แต่ในขั้นตอนนี้คุณต้องใช้นิพจน์นี้:

CASE
WHEN abs( "ALKUKULMA" - "LOPPUKULMA") < 360
THEN
make_line(
 $geometry,
 make_point(
  $x + 1000*cos(radians(90 - "LOPPUKULMA")),
  $y + 1000*sin(radians(90 - "LOPPUKULMA"))
  )
)
END

เราเพิ่งกำหนดบรรทัดแรกซึ่งชี้ไปยังจุดที่ภาคแสงสิ้นสุด บรรทัดนี้มีความยาว 1,000 ม. และสร้างขึ้นเฉพาะเมื่อมุมเปิดของแสงเซกเตอร์ไม่ใช่มุมกลม (เกิดขึ้นเพื่อหลีกเลี่ยงว่าเส้นจะแตกเป็นวงกลมทั้งหมด)

4) ตัวสร้างรูปทรงเรขาคณิตหมายเลข 3

แทรกนิพจน์นี้ในExpressionฟิลด์:

CASE

WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" >= "LOPPUKULMA"
THEN
difference(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x + 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") <= 180 AND "ALKUKULMA" <= "LOPPUKULMA"
THEN
intersection(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x + 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y + 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") > 180 AND "ALKUKULMA" >= "LOPPUKULMA"
THEN
intersection(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x - 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y - 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)

WHEN abs("ALKUKULMA" - "LOPPUKULMA") > 180 AND "ALKUKULMA" <= "LOPPUKULMA"
THEN
difference(
 boundary(
  buffer(
   $geometry, 900)
   ),
  make_polygon(
   geom_from_wkt(
    geom_to_wkt(
     make_line(
      $geometry,
      make_point($x + 2000*cos(radians(90 - "ALKUKULMA" )), $y + 2000*sin(radians((90 - "ALKUKULMA" )))),
      make_point($x - 2000*cos(radians(90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )), $y - 2000*sin(radians((90 - ("LOPPUKULMA" + "ALKUKULMA")/2 )))),
      make_point($x + 2000*cos(radians(90 - "LOPPUKULMA")), $y + 2000*sin(radians((90 - "LOPPUKULMA")))),
      $geometry)
   )  
  )
 )
)


END

เราเพิ่งกำหนดส่วนโค้งระหว่างจุดเริ่มต้นและจุดสิ้นสุดของเซกเตอร์แสง (โปรดทราบว่า2000เป็นค่าโดยพลการเนื่องจากฉันพยายามสร้างรูปหลายเหลี่ยมเพื่อตัดกับขอบเขตของวงกลมที่มีรัศมี 900 เมตร)

นอกจากนี้เราต้องตั้งค่าสีที่เก็บไว้ใน"VARIS"สนาม ในการทำเช่นนี้เราต้องระบุด้วยนิพจน์ที่กำหนดเอง ทำตามลูกศรในภาพด้านล่าง:

ป้อนคำอธิบายรูปภาพที่นี่

จากนั้นพิมพ์นิพจน์นี้หลังจากคลิกEdit...ปุ่ม:

CASE
WHEN  "VARIS" = 'vi' THEN color_rgb(51,160,44)
WHEN "VARIS" = 'v' THEN color_rgb(255,255,255)
WHEN "VARIS" = 'p' THEN color_rgb(227,26,28)
END

โปรดทราบว่าสำหรับเลเยอร์สัญลักษณ์นี้ฉันสร้างสองบรรทัด: บรรทัดบนกำหนดสีที่จะใช้ (อันที่จริงฉันตั้งค่านิพจน์ที่กำหนดเองสำหรับอันนี้) ในขณะที่อันที่ต่ำกว่านั้นมีประโยชน์สำหรับการกำหนดขอบดำ (มันจะมี ความกว้างที่ใหญ่กว่าหนึ่งบรรทัดบน) อย่าลืมตั้งFlatให้เป็นCap styleทั้งสองบรรทัดเพื่อหลีกเลี่ยงการซ้อนทับสีใด ๆ


การติดฉลาก

1) การตั้งค่าฉลาก

ไปที่Layer Properties> Labelsและตามปกติให้ทำตามลูกศรสีแดง:

ป้อนคำอธิบายรูปภาพที่นี่

จากนั้นพิมพ์นิพจน์นี้:

CASE
WHEN "VARIS" = 'vi' THEN 'G'
WHEN "VARIS" = 'v' THEN 'W'
WHEN "VARIS" = 'p' THEN 'R'
END

เราเพิ่งกำหนดกฎสีโดยใช้ค่าที่เก็บไว้ใน"VARIS"ฟิลด์

2) การตั้งค่าตำแหน่งสำหรับฉลาก

เลือกPlacementตัวเลือกในเมนูและเลือกLabelsOffset from point

จากนั้นตามภาพด้านล่าง:

ป้อนคำอธิบายรูปภาพที่นี่

ทำตามลูกศรสีแดงและพิมพ์นิพจน์นี้:

CASE
WHEN "ALKUKULMA" > "LOPPUKULMA"
THEN
concat(
 -1000*cos(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2)),
  ',',
  1000*sin(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2))
)
WHEN "ALKUKULMA" <= "LOPPUKULMA"
THEN
concat(
 1000*cos(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2)),
  ',',
  -1000*sin(radians(90 - ("ALKUKULMA" + "LOPPUKULMA")/2))
)
END

จากนั้นทำตามลูกศรสีเขียวและพิมพ์นิพจน์นี้:

CASE
WHEN "ALKUKULMA" >= "LOPPUKULMA"
THEN
180-(("ALKUKULMA" + "LOPPUKULMA")/2)
WHEN "ALKUKULMA" < "LOPPUKULMA"
THEN
- (("ALKUKULMA" + "LOPPUKULMA")/2)
END

ผลสุดท้าย

หากคุณทำภารกิจก่อนหน้าอย่างถูกต้องคุณควรจะได้รับผลลัพธ์นี้:

ป้อนคำอธิบายรูปภาพที่นี่

โบนัส

เนื่องจากพารามิเตอร์รองมีมากเกินไปสำหรับการครอบคลุมอย่างสมบูรณ์ภายในคำตอบนี้ฉันได้แนบสไตล์ที่นี่ : คุณอาจเปิดรหัสนี้ด้วยโปรแกรมแก้ไขข้อความใด ๆ และบันทึกเป็นไฟล์ QGIS Layer Style (เช่นมี.qmlส่วนขยาย)

สไตล์ข้างต้นถูกสร้างขึ้นโดยใช้QGIS 2.18.4 (ต้องมีชื่อเดียวกันกับรูปร่างไฟล์ที่คุณใช้)


3
ดูดีจริงๆแสดงพลังของเครื่องกำเนิดเรขาคณิต การแสดงช้าหรือไม่
HeikkiVesanto

2
@Vesanto ฉันทดสอบในจุดหนึ่งที่มีหกคุณสมบัติ (เช่นไฟหกภาค) และมันแสดงผลทันที ฉันคิดว่ามันควรจะรวดเร็วเช่นกันเมื่อต้องรับมือกับคุณสมบัติหลายร้อยอย่างเพราะไม่มีการเรียกผู้ให้บริการหรือสิ่งที่คล้ายกัน แต่มีเพียงการดำเนินการทางคณิตศาสตร์และรูปทรงเรขาคณิตเพียงไม่กี่อย่างเช่น Know Know Text
mgri

2
คำถาม / คำตอบเช่นนี้แสดงให้เห็นว่า QGIS หลากหลายสามารถเป็นจริงได้
Joseph

1
@ มม. คุณคือเดอะมาสเตอร์ทางออกที่ดีอย่างน่าอัศจรรย์และคำอธิบายที่ยอดเยี่ยมเกี่ยวกับงานจำนวนมากขอขอบคุณ !!
Benjamin Donner

1
@ มม. ภูเขาในภูมิภาคนี้ควรตั้งชื่อตามคุณขอบคุณ !! ฉันได้ทดสอบไปเล็กน้อยและไม่พบปัญหากับโซลูชันเพิ่มเติมของคุณ :)!
Benjamin Donner
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.